diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..03388e2e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,57 @@ +# EditorConfig helps developers define and maintain consistent coding styles between different editors and IDEs +# editorconfig.org + +root = true + +[*] +indent_style = space +indent_size = 4 + +# We recommend you to keep these unchanged +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.js] +indent_size = 2 + +[*.xml] +indent_size = 4 + +[*.groovy] +indent_size = 4 + +[*.gsp] +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false +indent_size = 4 + +[*.{yml,yaml}] +indent_size = 2 + +[*.json] +indent_size = 2 + +[*.gdoc] +indent_size = 2 + +[*.html] +indent_size = 2 + +[*.css] +indent_size = 2 + +[.github/release-drafter.yml] +insert_final_newline = false + +[.github/renovate.json] +insert_final_newline = false + +[gradle/libs.versions.toml] +insert_final_newline = false + +[grails-app/i18n/*.properties] +insert_final_newline = false diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index cc494587..b916f1f5 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -76,4 +76,4 @@ jobs: COMMIT_EMAIL: ${{ env.GIT_USER_EMAIL }} COMMIT_NAME: ${{ env.GIT_USER_NAME }} FOLDER: build/docs/manual - GH_TOKEN: ${{ secrets.GH_TOKEN }} \ No newline at end of file + GH_TOKEN: ${{ secrets.GH_TOKEN }} diff --git a/.github/workflows/release-notes.yml b/.github/workflows/release-notes.yml index 24914965..ffb709da 100644 --- a/.github/workflows/release-notes.yml +++ b/.github/workflows/release-notes.yml @@ -8,13 +8,13 @@ on: pull_request: types: [opened, reopened, synchronize, labeled] pull_request_target: - types: [opened, reopened, synchronize, labeled] + types: [opened, reopened, synchronize, labeled] workflow_dispatch: jobs: release_notes: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Check if it has release drafter config file id: check_release_drafter run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f07accd2..cd603bda 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -63,4 +63,4 @@ jobs: - name: Run post-release if: steps.publish_to_sonatype.outcome == 'success' - uses: micronaut-projects/github-actions/post-release@master \ No newline at end of file + uses: micronaut-projects/github-actions/post-release@master diff --git a/README.md b/README.md index 889f4fab..1ae574d9 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,12 @@ The Grails mail plugin provides a convenient DSL for _sending_ email. It support Mail can be sent using the `mailService.sendMail` method. Here is an example… ```groovy mailService.sendMail { - to 'fred@gmail.com', 'ginger@gmail.com' - from 'john@gmail.com' - cc 'marge@gmail.com', 'ed@gmail.com' - bcc 'joe@gmail.com' - subject 'Hello John' - text 'this is some text' + to 'fred@gmail.com', 'ginger@gmail.com' + from 'john@gmail.com' + cc 'marge@gmail.com', 'ed@gmail.com' + bcc 'joe@gmail.com' + subject 'Hello John' + text 'this is some text' } ``` @@ -40,4 +40,4 @@ Issues can be raised via [GitHub Issues](https://github.com/grails/grails-mail/i Pull requests are the preferred method for submitting contributions. Please open an issue via that issue tracker link above and create an issue describing what your contribution addresses. -If you are contributing documentation, raising an issue is not necessary. \ No newline at end of file +If you are contributing documentation, raising an issue is not necessary. diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 61d91892..4cef06e7 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -5,4 +5,4 @@ repositories { dependencies { implementation buildsrcLibs.nexus.publish.gradle.plugin implementation buildsrcLibs.grails.gradle.plugin -} \ No newline at end of file +} diff --git a/buildSrc/settings.gradle b/buildSrc/settings.gradle index 6cd9ab17..59ad2808 100644 --- a/buildSrc/settings.gradle +++ b/buildSrc/settings.gradle @@ -4,4 +4,4 @@ dependencyResolutionManagement { from(files('../gradle/buildsrc.libs.versions.toml')) } } -} \ No newline at end of file +} diff --git a/gradle/documentation-config.gradle b/gradle/documentation-config.gradle index f12f5500..4777397c 100644 --- a/gradle/documentation-config.gradle +++ b/gradle/documentation-config.gradle @@ -29,4 +29,4 @@ tasks.withType(PublishGuideTask).configureEach { classpath = configurations.guideConfiguration javadocDir = null propertiesFile = layout.projectDirectory.file('src/docs/guide.properties').asFile -} \ No newline at end of file +} diff --git a/gradle/grails-plugin-config.gradle b/gradle/grails-plugin-config.gradle index e516cd9f..885d0b72 100644 --- a/gradle/grails-plugin-config.gradle +++ b/gradle/grails-plugin-config.gradle @@ -5,4 +5,4 @@ tasks.named('jar', Jar) { enabled = true // Enable the jar task again, as the bootJar task has been disabled archiveClassifier = '' // Remove '-plain' suffix from jar file name exclude('_testemails', 'messages*.properties') -} \ No newline at end of file +} diff --git a/gradle/java-config.gradle b/gradle/java-config.gradle index f5363192..09b415ec 100644 --- a/gradle/java-config.gradle +++ b/gradle/java-config.gradle @@ -2,4 +2,4 @@ java { sourceCompatibility = JavaVersion.VERSION_11 withSourcesJar() withJavadocJar() -} \ No newline at end of file +} diff --git a/gradle/publishing.gradle b/gradle/publishing.gradle index df06f69d..f2d36c17 100644 --- a/gradle/publishing.gradle +++ b/gradle/publishing.gradle @@ -122,4 +122,4 @@ if (isReleaseVersion) { //do not generate extra load on Nexus with new staging repository if signing fails tasks.withType(InitializeNexusStagingRepository).configureEach { shouldRunAfter = tasks.withType(Sign) -} \ No newline at end of file +} diff --git a/grails-app/init/grails/plugins/mail/Application.groovy b/grails-app/init/grails/plugins/mail/Application.groovy index 9476c015..5ddd74a3 100644 --- a/grails-app/init/grails/plugins/mail/Application.groovy +++ b/grails-app/init/grails/plugins/mail/Application.groovy @@ -9,4 +9,4 @@ class Application extends GrailsAutoConfiguration { static void main(String[] args) { GrailsApp.run(Application) } -} \ No newline at end of file +} diff --git a/grails-app/services/grails/plugins/mail/MailService.groovy b/grails-app/services/grails/plugins/mail/MailService.groovy index 2a0dd6e6..ca36bad0 100644 --- a/grails-app/services/grails/plugins/mail/MailService.groovy +++ b/grails-app/services/grails/plugins/mail/MailService.groovy @@ -37,13 +37,13 @@ import java.util.concurrent.TimeUnit @CompileStatic class MailService implements InitializingBean, DisposableBean { - MailConfigurationProperties mailConfigurationProperties + MailConfigurationProperties mailConfigurationProperties MailMessageBuilderFactory mailMessageBuilderFactory - private ThreadPoolExecutor mailExecutorService + private ThreadPoolExecutor mailExecutorService - private static final Integer DEFAULT_POOL_SIZE = 5 - private static final Bindable CONFIG_BINDABLE = Bindable.of(MailConfigurationProperties) + private static final Integer DEFAULT_POOL_SIZE = 5 + private static final Bindable CONFIG_BINDABLE = Bindable.of(MailConfigurationProperties) MailMessage sendMail(MailConfigurationProperties properties, @DelegatesTo(strategy = Closure.DELEGATE_FIRST, value = MailMessageBuilder) Closure callable) { if (disabled) { @@ -57,40 +57,40 @@ class MailService implements InitializingBean, DisposableBean { return messageBuilder.sendMessage(mailExecutorService) } - MailMessage sendMail(Config config, @DelegatesTo(strategy = Closure.DELEGATE_FIRST, value = MailMessageBuilder) Closure callable) { - return sendMail(toMailProperties(config), callable) - } + MailMessage sendMail(Config config, @DelegatesTo(strategy = Closure.DELEGATE_FIRST, value = MailMessageBuilder) Closure callable) { + return sendMail(toMailProperties(config), callable) + } MailMessage sendMail(@DelegatesTo(strategy = Closure.DELEGATE_FIRST, value = MailMessageBuilder) Closure callable) { return sendMail(mailConfigurationProperties, callable) } - private static MailConfigurationProperties toMailProperties(Config config) { - def propertySource = new PropertiesPropertySource('mailProperties', config.toProperties()) - def configurationPropertySources = ConfigurationPropertySources.from(propertySource) - def binder = new Binder(configurationPropertySources) - return binder.bind(MailConfigurationProperties.PREFIX, CONFIG_BINDABLE).get() - } + private static MailConfigurationProperties toMailProperties(Config config) { + def propertySource = new PropertiesPropertySource('mailProperties', config.toProperties()) + def configurationPropertySources = ConfigurationPropertySources.from(propertySource) + def binder = new Binder(configurationPropertySources) + return binder.bind(MailConfigurationProperties.PREFIX, CONFIG_BINDABLE).get() + } boolean isDisabled() { - mailConfigurationProperties.disabled + return mailConfigurationProperties.disabled } - void setPoolSize(Integer poolSize){ - mailExecutorService.setMaximumPoolSize(poolSize ?: DEFAULT_POOL_SIZE) - mailExecutorService.setCorePoolSize(poolSize ?: DEFAULT_POOL_SIZE) - } + void setPoolSize(Integer poolSize) { + mailExecutorService.setMaximumPoolSize(poolSize ?: DEFAULT_POOL_SIZE) + mailExecutorService.setCorePoolSize(poolSize ?: DEFAULT_POOL_SIZE) + } - @Override - void destroy() throws Exception { - mailExecutorService.shutdown() - mailExecutorService.awaitTermination(10, TimeUnit.SECONDS) - } + @Override + void destroy() throws Exception { + mailExecutorService.shutdown() + mailExecutorService.awaitTermination(10, TimeUnit.SECONDS) + } - @Override - void afterPropertiesSet() throws Exception { - mailExecutorService = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new LinkedBlockingQueue()) - mailExecutorService.allowCoreThreadTimeOut(true) - setPoolSize(mailConfigurationProperties.poolSize) - } + @Override + void afterPropertiesSet() throws Exception { + mailExecutorService = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new LinkedBlockingQueue()) + mailExecutorService.allowCoreThreadTimeOut(true) + setPoolSize(mailConfigurationProperties.poolSize) + } } diff --git a/grails-app/views/_testemails/i18ntest.gsp b/grails-app/views/_testemails/i18ntest.gsp index a8c66c37..87b2ffde 100644 --- a/grails-app/views/_testemails/i18ntest.gsp +++ b/grails-app/views/_testemails/i18ntest.gsp @@ -1,4 +1,4 @@ <%@ page contentType="text/html" %> - \ No newline at end of file + diff --git a/src/docs/guide.properties b/src/docs/guide.properties index 1bb01e2c..5c05890a 100644 --- a/src/docs/guide.properties +++ b/src/docs/guide.properties @@ -1,2 +1,2 @@ title=Grails Mail Plugin -authors=The Grails Team \ No newline at end of file +authors=The Grails Team diff --git a/src/docs/guide/1. Introduction.gdoc b/src/docs/guide/1. Introduction.gdoc index 4b1abd8a..d6795455 100644 --- a/src/docs/guide/1. Introduction.gdoc +++ b/src/docs/guide/1. Introduction.gdoc @@ -4,12 +4,12 @@ Mail can be sent using the @mailService@ via the @sendMail@ method. Here is an e {code} mailService.sendMail { - to "fred@gmail.com", "ginger\@gmail.com" - from "john@gmail.com" - cc "marge@gmail.com", "ed\@gmail.com" - bcc "joe@gmail.com" - subject "Hello John" - text "this is some text" + to "fred@gmail.com", "ginger\@gmail.com" + from "john@gmail.com" + cc "marge@gmail.com", "ed\@gmail.com" + bcc "joe@gmail.com" + subject "Hello John" + text "this is some text" } {code} @@ -19,8 +19,8 @@ The @sendMail@ method is injected into all controllers to simplify access: {code} sendMail { - to "fred@g2one.com" - subject "Hello Fred" - text "How are you?" + to "fred@g2one.com" + subject "Hello Fred" + text "How are you?" } -{code} \ No newline at end of file +{code} diff --git a/src/docs/guide/2.1 SMTP Server Configuration.gdoc b/src/docs/guide/2.1 SMTP Server Configuration.gdoc index 888e490e..157521e6 100644 --- a/src/docs/guide/2.1 SMTP Server Configuration.gdoc +++ b/src/docs/guide/2.1 SMTP Server Configuration.gdoc @@ -2,16 +2,16 @@ By default the plugin assumes an unsecured mail server configured on port 25, ge {code} grails { - mail { - host = "smtp.gmail.com" - port = 465 - username = "youracount@gmail.com" - password = "yourpassword" - props = ["mail.smtp.auth":"true", - "mail.smtp.socketFactory.port":"465", - "mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory", - "mail.smtp.socketFactory.fallback":"false"] - } + mail { + host = "smtp.gmail.com" + port = 465 + username = "youracount@gmail.com" + password = "yourpassword" + props = ["mail.smtp.auth":"true", + "mail.smtp.socketFactory.port":"465", + "mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory", + "mail.smtp.socketFactory.fallback":"false"] + } } {code} @@ -19,14 +19,14 @@ And the configuration for sending via a Hotmail/Live account: {code} grails { - mail { - host = "smtp.live.com" - port = 587 - username = "youracount@live.com" - password = "yourpassword" - props = ["mail.smtp.starttls.enable":"true", - "mail.smtp.port":"587"] - } + mail { + host = "smtp.live.com" + port = 587 + username = "youracount@live.com" + password = "yourpassword" + props = ["mail.smtp.starttls.enable":"true", + "mail.smtp.port":"587"] + } } {code} diff --git a/src/docs/guide/2.2 Defaults Configuration.gdoc b/src/docs/guide/2.2 Defaults Configuration.gdoc index 9a952157..09ae65e7 100644 --- a/src/docs/guide/2.2 Defaults Configuration.gdoc +++ b/src/docs/guide/2.2 Defaults Configuration.gdoc @@ -10,4 +10,4 @@ You can also set the default "to" address to use for messages in Config using: {code} grails.mail.default.to = "user@yourhost.com" -{code} \ No newline at end of file +{code} diff --git a/src/docs/guide/3.1 Sender And Recipient.gdoc b/src/docs/guide/3.1 Sender And Recipient.gdoc index 70fe3531..066d50e8 100644 --- a/src/docs/guide/3.1 Sender And Recipient.gdoc +++ b/src/docs/guide/3.1 Sender And Recipient.gdoc @@ -41,4 +41,4 @@ sendMail { The @from@ method accepts one string value email address using the syntax of "RFC822":http://www.ietf.org/rfc/rfc822.txt. Typical address syntax is of the form @"user\@host.domain"@ or @"Personal Name "@. -If no value is provided for @from@ when sending an email, the _default from address_ will be used. \ No newline at end of file +If no value is provided for @from@ when sending an email, the _default from address_ will be used. diff --git a/src/docs/guide/3.2 Message Content.gdoc b/src/docs/guide/3.2 Message Content.gdoc index c0dc602d..66249996 100644 --- a/src/docs/guide/3.2 Message Content.gdoc +++ b/src/docs/guide/3.2 Message Content.gdoc @@ -79,4 +79,4 @@ Both the @text@ and @html@ methods support specifying a view to render to form t * The _view_ is the absolute path (or relative to the current controller if during a request) to the GSP, just like the existing Grails @render@ method. * The _plugin_ parameter is only necessary if the view you wish to render comes from a plugin, just like the existing Grails @render@ method. -* The _model_ parameter is a map representing the model the GSP will see for rendering data, just like the existing Grails @render@ method. \ No newline at end of file +* The _model_ parameter is a map representing the model the GSP will see for rendering data, just like the existing Grails @render@ method. diff --git a/src/docs/guide/3.3 Attachments.gdoc b/src/docs/guide/3.3 Attachments.gdoc index 6bddb676..7679a663 100644 --- a/src/docs/guide/3.3 Attachments.gdoc +++ b/src/docs/guide/3.3 Attachments.gdoc @@ -96,4 +96,4 @@ The mail plugin supports using either a @byte\[\]@, @File@, or "@InputStreamSour In the case of the variants that take a @File@ that do not specify a content id, the name of the file will be used. -In the case of the variants that take a @File@ that do not specify a content type, the content type will be guessed based on the file extension. \ No newline at end of file +In the case of the variants that take a @File@ that do not specify a content type, the content type will be guessed based on the file extension. diff --git a/src/docs/guide/4. Testing.gdoc b/src/docs/guide/4. Testing.gdoc index a1799c16..1c36b2a5 100644 --- a/src/docs/guide/4. Testing.gdoc +++ b/src/docs/guide/4. Testing.gdoc @@ -26,4 +26,4 @@ The preferred approach is to use the existing "grails-greenmail":http://www.grai The advantage of this approach is that it is as close as possible to real world and gives you access to the sent email in your tests. The disadvantage is that it is another plugin dependency. -Consult the documentation for the plugin for more information. \ No newline at end of file +Consult the documentation for the plugin for more information. diff --git a/src/integration-test/groovy/grails/plugins/mail/MailServiceSpec.groovy b/src/integration-test/groovy/grails/plugins/mail/MailServiceSpec.groovy index e0d78179..7d054069 100644 --- a/src/integration-test/groovy/grails/plugins/mail/MailServiceSpec.groovy +++ b/src/integration-test/groovy/grails/plugins/mail/MailServiceSpec.groovy @@ -19,6 +19,8 @@ package grails.plugins.mail import com.icegreen.greenmail.util.GreenMail import com.icegreen.greenmail.util.ServerSetupTest import grails.testing.mixin.integration.Integration +import groovy.xml.XmlSlurper +import groovy.xml.slurpersupport.GPathResult import org.grails.io.support.ClassPathResource import org.springframework.core.io.FileSystemResource import org.springframework.mail.MailMessage @@ -44,15 +46,15 @@ class MailServiceSpec extends Specification { MailService nonMimeCapableMailService MailMessageContentRenderer mailMessageContentRenderer - @Shared + @Shared GreenMail greenMail = new GreenMail(ServerSetupTest.SMTP) def setupSpec() { - greenMail.start() + greenMail.start() } def cleanupSpec() { - greenMail.stop() + greenMail.stop() } def setup() { @@ -92,23 +94,23 @@ class MailServiceSpec extends Specification { from 'king@g2one.com' } then: - message instanceof SimpleMailMessage + message instanceof SimpleMailMessage "Hello John" == ((SimpleMailMessage)message).getSubject() - 'this is some text' ==message.getText() + 'this is some text' == message.getText() 'fred@g2one.com' == message.to[0] 'king@g2one.com' == message.from } void testAsyncSendSimpleMessage() { - when: + when: MailMessage message = nonMimeCapableMailService.sendMail { - async true - to "fred@g2one.com" - title "Hello John" - body 'this is some text' - from 'king@g2one.com' + async true + to "fred@g2one.com" + title "Hello John" + body 'this is some text' + from 'king@g2one.com' } - then: + then: message instanceof SimpleMailMessage "Hello John" == ((SimpleMailMessage)message).getSubject() 'this is some text' == message.getText() @@ -117,62 +119,59 @@ class MailServiceSpec extends Specification { } void testSendToMultipleRecipients() { - when: + when: MailMessage message = nonMimeCapableMailService.sendMail { - to "fred@g2one.com", "ginger@g2one.com" - title "Hello John" - body 'this is some text' + to "fred@g2one.com", "ginger@g2one.com" + title "Hello John" + body 'this is some text' } - then: + then: message.subject == "Hello John" message.text == "this is some text" message.to[0] == "fred@g2one.com" message.to[1] == "ginger@g2one.com" } - - - void testSendToMultipleRecipientsUsingList() { - when: + when: MailMessage message = nonMimeCapableMailService.sendMail { to(["fred@g2one.com", "ginger@g2one.com"]) title "Hello John" body 'this is some text' } - then: + then: message.getTo()[0] == "fred@g2one.com" message.getTo()[1] == "ginger@g2one.com" } void testSendToMultipleCCRecipientsUsingList() { - when: + when: MailMessage message = nonMimeCapableMailService.sendMail { to 'joe@g2one.com' cc(["fred@g2one.com", "ginger@g2one.com"]) title "Hello John" body 'this is some text' } - then: + then: "fred@g2one.com" == message.cc[0] "ginger@g2one.com" == message.cc[1] } void testSendToMultipleBCCRecipientsUsingList() { - when: + when: MailMessage message = nonMimeCapableMailService.sendMail { to("joe@g2one.com") bcc(["fred@g2one.com", "ginger@g2one.com"]) title "Hello John" body 'this is some text' } - then: + then: "fred@g2one.com" == message.bcc[0] "ginger@g2one.com" == message.bcc[1] } void testSendToMultipleRecipientsAndCC() { - when: + when: MailMessage message = nonMimeCapableMailService.sendMail { to "fred@g2one.com", "ginger@g2one.com" from "john@g2one.com" @@ -181,7 +180,7 @@ class MailServiceSpec extends Specification { title "Hello John" body 'this is some text' } - then: + then: message instanceof SimpleMailMessage "Hello John" == ((SimpleMailMessage)message).getSubject() message.text == 'this is some text' @@ -200,115 +199,113 @@ class MailServiceSpec extends Specification { } void testSendMailWithEnvelopeFrom() { - given: - - def message = mimeCapableMailService.sendMail { + given: + MailMessage message = mimeCapableMailService.sendMail { to "fred@g2one.com" title "Hello John" body 'this is some text' from 'king@g2one.com' envelopeFrom 'peter@g2one.com' } - when: + when: def msg = message.mimeMessage - def greenMsg = greenMail.getReceivedMessages()[0] - then: - msg.getSubject() == "Hello John" - msg.getFrom()[0].toString() == "king@g2one.com" - greenMsg.getHeader("Return-Path")[0] == "" + MimeMessage greenMsg = greenMail.getReceivedMessages()[0] + then: + msg.getSubject() == "Hello John" + msg.getFrom()[0].toString() == "king@g2one.com" + greenMsg.getHeader("Return-Path")[0] == "" } void testSendMailWithEnvelopeFromAndBasicMailSender() { when: - nonMimeCapableMailService.sendMail { - to "fred@g2one.com" - title "Hello John" - body 'this is some text' - from 'king@g2one.com' - envelopeFrom 'peter@g2one.com' - } + nonMimeCapableMailService.sendMail { + to "fred@g2one.com" + title "Hello John" + body 'this is some text' + from 'king@g2one.com' + envelopeFrom 'peter@g2one.com' + } then: - thrown GrailsMailException - + thrown GrailsMailException } void testSendHtmlMail() { - when: + when: MimeMailMessage message = mimeCapableMailService.sendMail { to "fred@g2one.com" subject "Hello John" html 'Hello World' - } - then: + } as MimeMailMessage + then: message.getMimeMessage().getSubject() == "Hello John" message.mimeMessage.contentType.startsWith('text/html') message.getMimeMessage().getContent() == 'Hello World' } void testSendMailView() { - when: + when: MimeMailMessage message = mimeCapableMailService.sendMail { to "fred@g2one.com" subject "Hello John" body(view: '/_testemails/test', model: [msg: 'hello']) - } - then: + } as MimeMailMessage + then: message.getMimeMessage().getSubject() == "Hello John" message.mimeMessage.contentType.startsWith('text/plain') message.getMimeMessage().getContent().trim() == 'Message is: hello' } void testSendMailViewText() { - when: + when: MimeMailMessage message = mimeCapableMailService.sendMail { to "fred@g2one.com" subject "Hello John" text view: '/_testemails/test', model: [msg: 'hello'] - } - then: - message.mimeMessage.contentType.startsWith('text/plain') + } as MimeMailMessage + then: + message.mimeMessage.contentType.startsWith('text/plain') message.getMimeMessage().getContent().trim() == 'Message is: hello' } void testSendMailViewHtmlMethod() { - when: + when: MimeMailMessage message = mimeCapableMailService.sendMail { to "fred@g2one.com" subject "Hello John" html view: '/_testemails/testhtml', model: [msg: 'hello'] - } - then: + } as MimeMailMessage + then: message.getMimeMessage().getSubject() == "Hello John" message.mimeMessage.contentType.startsWith('text/html') message.getMimeMessage().getContent().trim() == 'Message is: hello' } void testSendMailViewHTML() { - when: + when: MimeMailMessage message = mimeCapableMailService.sendMail { to "fred@g2one.com" subject "Hello John" body(view: '/_testemails/testhtml', model: [msg: 'hello']) - } - then: - message.getMimeMessage().getSubject() == "Hello John" - message.mimeMessage.contentType.startsWith('text/html') - message.getMimeMessage().getContent().trim() == 'Message is: hello' + } as MimeMailMessage + then: + message.getMimeMessage().getSubject() == "Hello John" + message.mimeMessage.contentType.startsWith('text/html') + message.getMimeMessage().getContent().trim() == 'Message is: hello' } void testSendMailViewWithTags() { - when: + when: MimeMailMessage message = mimeCapableMailService.sendMail { to "fred@g2one.com" subject "Hello John" body(view: '/_testemails/tagtest', model: [condition: true]) - } + } as MimeMailMessage MimeMailMessage message2 = mimeCapableMailService.sendMail { to "fred@g2one.com" subject "Hello John" body(view: '/_testemails/tagtest', model: [condition: false]) - } - then: + } as MimeMailMessage + then: message.getMimeMessage().getSubject() == "Hello John" message.getMimeMessage().getContent().trim() == 'Condition is true' @@ -318,13 +315,13 @@ class MailServiceSpec extends Specification { } void testSendMailViewNoModel() { - when: + when: MimeMailMessage message = mimeCapableMailService.sendMail { to "fred@g2one.com" subject "Hello John" body(view: '/_testemails/test') - } - then: + } as MimeMailMessage + then: message.getMimeMessage().getSubject() == "Hello John" message.getMimeMessage().getContentType()?.startsWith('text/plain') message.getMimeMessage().getContent().trim() == 'Message is:' @@ -335,7 +332,7 @@ class MailServiceSpec extends Specification { * specified headers to the underlying MIME message. */ void testSendMailWithHeaders() { - when: + when: MailMessage message = mimeCapableMailService.sendMail { headers "X-Mailing-List": "user@grails.codehaus.org", "Sender": "dilbert@somewhere.org" @@ -344,7 +341,7 @@ class MailServiceSpec extends Specification { body 'How are you?' } MimeMessage msg = ((MimeMailMessage)message).mimeMessageHelper.mimeMessage - then: + then: message instanceof MimeMailMessage msg.getHeader("X-Mailing-List")[0] == "user@grails.codehaus.org" @@ -360,19 +357,19 @@ class MailServiceSpec extends Specification { */ void testSendMailWithHeadersAndBasicMailSender() { when: - nonMimeCapableMailService.sendMail { - headers "Content-Type": "text/plain;charset=UTF-8", - "Sender": "dilbert@somewhere.org" - to "fred@g2one.com" - subject "Hello Fred" - body 'How are you?' - } + nonMimeCapableMailService.sendMail { + headers "Content-Type": "text/plain;charset=UTF-8", + "Sender": "dilbert@somewhere.org" + to "fred@g2one.com" + subject "Hello Fred" + body 'How are you?' + } then: - thrown GrailsMailException + thrown GrailsMailException } void testSendmailWithTranslations() { - when: + when: MailMessage message = mimeCapableMailService.sendMail { from 'neur0maner@gmail.com' to "neur0maner@gmail.com" @@ -389,16 +386,16 @@ class MailServiceSpec extends Specification { } MimeMessage msg = ((MimeMailMessage)message).mimeMessageHelper.mimeMessage MimeMessage msg2 = ((MimeMailMessage)message2).mimeMessageHelper.mimeMessage - final def slurper = new XmlSlurper() - def html = slurper.parseText(msg.content) - def html2 = slurper.parseText(msg2.content) - then: + final XmlSlurper slurper = new XmlSlurper() + GPathResult html = slurper.parseText(msg.content as String) + GPathResult html2 = slurper.parseText(msg2.content as String) + then: html.body.toString() == 'Translate this: Luis' html2.body.toString() == 'Traduis ceci: Luis' } void testSendmailWithByteArrayAttachment() { - when: + when: MailMessage message = mimeCapableMailService.sendMail { multipart true @@ -411,19 +408,19 @@ class MailServiceSpec extends Specification { html 'this is some text' } def content = ((MimeMailMessage)message).mimeMessage.content - then: + then: content.count == 2 content.getBodyPart(1).inputStream.text == 'Hello World' } void testSendmailWithByteArrayAndResourceAttachments() { - given: + given: File tmpFile - when: + when: MailMessage message = mimeCapableMailService.sendMail { multipart true - tmpFile = File.createTempFile('testSendmailWithAttachments',null) + tmpFile = File.createTempFile('testSendmailWithAttachments', null) tmpFile << 'Hello World' to "fred@g2one.com", "ginger@g2one.com" @@ -435,18 +432,17 @@ class MailServiceSpec extends Specification { attach 'fileName2', 'application/octet-stream', new FileSystemResource(tmpFile) html 'this is some text' } - def content=message.mimeMessage.content - then: + def content = message.mimeMessage.content + then: content.count == 3 content.getBodyPart(1).inputStream.text == 'Dear John' content.getBodyPart(2).inputStream.text == 'Hello World' - cleanup: + cleanup: tmpFile?.delete() } void testInlineAttachment() { - when: - + when: byte[] bytes = new ClassPathResource('assets/grailslogo.png').inputStream.bytes MailMessage message = mimeCapableMailService.sendMail { @@ -458,24 +454,24 @@ class MailServiceSpec extends Specification { inline 'abc123', 'image/png', bytes } def inlinePart = ((MimeMailMessage)message).mimeMessage.content.getBodyPart(0).content.getBodyPart("") - then: + then: inlinePart.inputStream.bytes == bytes } void testHtmlContentType() { - when: + when: MimeMessage msg = mimeCapableMailService.sendMail { to "fred@g2one.com" subject "test" html 'How are you?' }.mimeMessage - then: - msg.contentType.startsWith("text/html") + then: + msg.contentType.startsWith("text/html") msg.content == 'How are you?' } void testMultipart_html_first() { - when: + when: MimeMessage msg = mimeCapableMailService.sendMail { multipart true to "fred@g2one.com" @@ -484,7 +480,7 @@ class MailServiceSpec extends Specification { text 'How are you?' }.mimeMessage MimeMultipart mp = msg.content.getBodyPart(0).content.getBodyPart(0).content - then: + then: mp.count == 2 mp.getBodyPart(0).contentType.startsWith('text/plain') mp.getBodyPart(0).content == 'How are you?' @@ -493,7 +489,7 @@ class MailServiceSpec extends Specification { } void testMultipart_text_first() { - when: + when: MimeMessage msg = mimeCapableMailService.sendMail { multipart true to "fred@g2one.com" @@ -502,7 +498,7 @@ class MailServiceSpec extends Specification { html 'How are you?' }.mimeMessage MimeMultipart mp = msg.content.getBodyPart(0).content.getBodyPart(0).content - then: + then: mp.count == 2 mp.getBodyPart(0).contentType.startsWith('text/plain') mp.getBodyPart(0).content == 'How are you?' @@ -529,8 +525,8 @@ class MailServiceSpec extends Specification { content.getBodyPart(0) instanceof MimeBodyPart and: - MimeBodyPart mimeBodyPart = content.getBodyPart(0) - MimeMultipart mp = mimeBodyPart.content + MimeBodyPart mimeBodyPart = content.getBodyPart(0) as MimeBodyPart + MimeMultipart mp = mimeBodyPart.content as MimeMultipart mp.count == 2 mp.getBodyPart(0) instanceof MimeBodyPart @@ -551,7 +547,7 @@ class MailServiceSpec extends Specification { to "fred@g2one.com" subject "Hello John" body(view: '/test', model: [msg: 'hello']) - } + } as MimeMailMessage then: message.getMimeMessage().getSubject() == "Hello John" message.mimeMessage.contentType.startsWith('text/plain') == true @@ -572,17 +568,18 @@ class MailServiceSpec extends Specification { // } private List to(MimeMessage msg) { - msg.getRecipients(Message.RecipientType.TO)*.toString() + return msg.getRecipients(Message.RecipientType.TO)*.toString() } private List cc(MimeMessage msg) { - msg.getRecipients(Message.RecipientType.CC)*.toString() + return msg.getRecipients(Message.RecipientType.CC)*.toString() } private List bcc(MimeMessage msg) { - msg.getRecipients(Message.RecipientType.BCC)*.toString() + return msg.getRecipients(Message.RecipientType.BCC)*.toString() } } + class SimpleMailSender implements MailSender { void send(SimpleMailMessage simpleMessage) {} void send(SimpleMailMessage[] simpleMessages) {} diff --git a/src/integration-test/resources/logback-test.xml b/src/integration-test/resources/logback-test.xml index 2f573347..bf619ea9 100644 --- a/src/integration-test/resources/logback-test.xml +++ b/src/integration-test/resources/logback-test.xml @@ -13,4 +13,4 @@ - \ No newline at end of file + diff --git a/src/main/groovy/grails/plugins/mail/MailGrailsPlugin.groovy b/src/main/groovy/grails/plugins/mail/MailGrailsPlugin.groovy index 2fb7483f..0a638d2e 100644 --- a/src/main/groovy/grails/plugins/mail/MailGrailsPlugin.groovy +++ b/src/main/groovy/grails/plugins/mail/MailGrailsPlugin.groovy @@ -18,7 +18,7 @@ package grails.plugins.mail import grails.plugins.Plugin class MailGrailsPlugin extends Plugin { - + def grailsVersion = '6.0.0 > *' def author = 'The Grails team' def authorEmail = 'info@grails.org' diff --git a/src/main/groovy/grails/plugins/mail/MailMessageBuilder.groovy b/src/main/groovy/grails/plugins/mail/MailMessageBuilder.groovy index 3153fec5..e8ded22f 100644 --- a/src/main/groovy/grails/plugins/mail/MailMessageBuilder.groovy +++ b/src/main/groovy/grails/plugins/mail/MailMessageBuilder.groovy @@ -62,7 +62,7 @@ class MailMessageBuilder { private String envelopeFrom private int multipart = MimeMessageHelper.MULTIPART_MODE_NO - private boolean async = false + private boolean async = false private List inlines = [] @@ -95,7 +95,7 @@ class MailMessageBuilder { message.setTo(defaultTo) } } - message + return message } MailMessage sendMessage(ExecutorService executorService) { @@ -113,17 +113,17 @@ class MailMessageBuilder { sendingMsg.envelopeFrom = envelopeFrom } - if (async) { - executorService.execute({ - try { - send(sendingMsg) - } catch(Throwable t) { - log.error('Failed to send email', t) - } - } as Runnable) - } else { - send(sendingMsg) - } + if (async) { + executorService.execute({ + try { + send(sendingMsg) + } catch(Throwable t) { + log.error('Failed to send email', t) + } + } as Runnable) + } else { + send(sendingMsg) + } log.trace('Sent mail {} ...', getDescription(message as Message)) @@ -163,20 +163,20 @@ class MailMessageBuilder { } MailMessage msg = getMessage() - if (msg instanceof MimeMailMessage) { - MimeMessage mimeMessage = (msg as MimeMailMessage).mimeMessageHelper.mimeMessage - headers.each { name, value -> - String nameString = name?.toString() - String valueString = value?.toString() - - Assert.hasText(nameString, 'header names cannot be null or empty') - Assert.hasText(valueString, "header value for '$nameString' cannot be null") - - mimeMessage.setHeader(nameString, valueString) - } - } else { - throw new GrailsMailException('Mail message builder is not mime capable so headers cannot be set') - } + if (msg instanceof MimeMailMessage) { + MimeMessage mimeMessage = (msg as MimeMailMessage).mimeMessageHelper.mimeMessage + headers.each { name, value -> + String nameString = name?.toString() + String valueString = value?.toString() + + Assert.hasText(nameString, 'header names cannot be null or empty') + Assert.hasText(valueString, "header value for '$nameString' cannot be null") + + mimeMessage.setHeader(nameString, valueString) + } + } else { + throw new GrailsMailException('Mail message builder is not mime capable so headers cannot be set') + } } void to(Object[] args) { @@ -232,7 +232,7 @@ class MailMessageBuilder { Assert.hasText(value, 'envelope from cannot be null or 0 length') envelopeFrom = value } - + void title(CharSequence title) { Assert.notNull(title, 'title cannot be null') subject(title) @@ -265,7 +265,8 @@ class MailMessageBuilder { if (!params.view) { throw new GrailsMailException('no view specified') } - mailMessageContentRenderer.render(new StringWriter(), params.view as String, params.model as Map, locale, params.plugin as String) + return mailMessageContentRenderer.render(new StringWriter(), params.view as String, + params.model as Map, locale, params.plugin as String) } void text(Map params) { @@ -367,7 +368,7 @@ class MailMessageBuilder { } assert multipart, 'message is not marked as "multipart"; use "multipart true" as the first line in your builder DSL' - getMessage() // ensure that helper is initialized + getMessage() // ensure that helper is initialized if (isAttachment) { helper.addAttachment(MimeUtility.encodeWord(id), toAdd, contentType) } else { @@ -376,14 +377,14 @@ class MailMessageBuilder { } boolean isMimeCapable() { - mailSender instanceof JavaMailSender + return mailSender instanceof JavaMailSender } protected String[] toDestinationAddresses(addresses) { if (overrideAddress) { addresses = addresses.collect { overrideAddress } } - addresses.collect { it?.toString() } as String[] + return addresses.collect { it?.toString() } as String[] } static protected getDescription(SimpleMailMessage message) { @@ -418,4 +419,4 @@ class MailMessageBuilder { message.sentDate = new Date() message } -} \ No newline at end of file +} diff --git a/src/main/groovy/grails/plugins/mail/MailMessageBuilderFactory.groovy b/src/main/groovy/grails/plugins/mail/MailMessageBuilderFactory.groovy index c030813f..c1a25440 100644 --- a/src/main/groovy/grails/plugins/mail/MailMessageBuilderFactory.groovy +++ b/src/main/groovy/grails/plugins/mail/MailMessageBuilderFactory.groovy @@ -42,10 +42,10 @@ class MailMessageBuilderFactory { } MailMessageBuilder createBuilder(MailConfigurationProperties properties) { - new MailMessageBuilder(mailSender, properties, mailMessageContentRenderer) + return new MailMessageBuilder(mailSender, properties, mailMessageContentRenderer) } boolean isMimeCapable() { - mailSender instanceof JavaMailSender + return mailSender instanceof JavaMailSender } } diff --git a/src/main/groovy/grails/plugins/mail/MailMessageContentRender.groovy b/src/main/groovy/grails/plugins/mail/MailMessageContentRender.groovy index 0406956f..42c60b62 100644 --- a/src/main/groovy/grails/plugins/mail/MailMessageContentRender.groovy +++ b/src/main/groovy/grails/plugins/mail/MailMessageContentRender.groovy @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package grails.plugins.mail import groovy.transform.CompileStatic @@ -35,6 +34,6 @@ class MailMessageContentRender { } boolean isHtml() { - contentType in HTML_CONTENT_TYPES + return contentType in HTML_CONTENT_TYPES } } diff --git a/src/main/groovy/grails/plugins/mail/MailMessageContentRenderer.groovy b/src/main/groovy/grails/plugins/mail/MailMessageContentRenderer.groovy index daa43e59..4c7f161c 100644 --- a/src/main/groovy/grails/plugins/mail/MailMessageContentRenderer.groovy +++ b/src/main/groovy/grails/plugins/mail/MailMessageContentRenderer.groovy @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package grails.plugins.mail import grails.core.GrailsApplication @@ -71,7 +70,7 @@ class MailMessageContentRenderer { } MailMessageContentRender render(Writer out, String templateName, Map model, Locale locale, String pluginName = null) { - RenderEnvironment.with(grailsApplication.mainContext, out, locale) { RenderEnvironment env -> + return RenderEnvironment.with(grailsApplication.mainContext, out, locale) { RenderEnvironment env -> Template template = createTemplate(templateName, env.controllerName, pluginName) if (model instanceof Map) { template.make(model).writeTo(out) @@ -106,7 +105,7 @@ class MailMessageContentRenderer { throw new IllegalArgumentException("Could not locate mail body ${templateName}. Is it in a plugin? If so you must pass the plugin name in the [plugin] variable") } } - template as GroovyPageTemplate + return template as GroovyPageTemplate } protected String getContextPath(String pluginName) { @@ -117,7 +116,7 @@ class MailMessageContentRenderer { contextPath = "${plugin.pluginPath}/grails-app/views" } } - contextPath + return contextPath } private static class RenderEnvironment { @@ -125,7 +124,7 @@ class MailMessageContentRenderer { final PrintWriter out final Locale locale final ApplicationContext applicationContext - final LinkGenerator grailsLinkGenerator + final LinkGenerator grailsLinkGenerator private GrailsWebRequest originalRequestAttributes private GrailsWebRequest renderRequestAttributes @@ -135,7 +134,7 @@ class MailMessageContentRenderer { this.out = out instanceof PrintWriter ? out as PrintWriter : new PrintWriter(out) this.locale = locale this.applicationContext = applicationContext - this.grailsLinkGenerator = applicationContext.getBean('grailsLinkGenerator', LinkGenerator) + this.grailsLinkGenerator = applicationContext.getBean('grailsLinkGenerator', LinkGenerator) } private void init() { @@ -181,7 +180,7 @@ class MailMessageContentRenderer { /** * Establish an environment with a specific locale */ - static Object with(ApplicationContext applicationContext, Writer out, Locale locale, Closure block) { + static Object with(ApplicationContext applicationContext, Writer out, Locale locale, Closure block) { def env = new RenderEnvironment(applicationContext, out, locale) env.init() try { @@ -192,11 +191,11 @@ class MailMessageContentRenderer { } String getControllerName() { - renderRequestAttributes.controllerName + return renderRequestAttributes.controllerName } } - /* + /* * Creates the request object used during the GSP rendering pipeline for render operations outside a web request. * Created dynamically to avoid issues with different servlet API spec versions. */ @@ -211,7 +210,7 @@ class MailMessageContentRenderer { String contentType = null String characterEncoding = 'UTF-8' - Proxy.newProxyInstance(HttpServletRequest.classLoader, [HttpServletRequest] as Class[], new InvocationHandler() { + return Proxy.newProxyInstance(HttpServletRequest.classLoader, [HttpServletRequest] as Class[], new InvocationHandler() { Object invoke(proxy, Method method, Object[] args) { String methodName = method.name diff --git a/src/main/groovy/grails/plugins/mail/SendMail.groovy b/src/main/groovy/grails/plugins/mail/SendMail.groovy index 6f97ca7a..ebd7c0f9 100644 --- a/src/main/groovy/grails/plugins/mail/SendMail.groovy +++ b/src/main/groovy/grails/plugins/mail/SendMail.groovy @@ -27,10 +27,10 @@ import org.springframework.mail.MailMessage @Enhances([DefaultGrailsServiceClass.SERVICE, DefaultGrailsControllerClass.CONTROLLER]) trait SendMail { - @Autowired - ApplicationContext applicationContext + @Autowired + ApplicationContext applicationContext - MailMessage sendMail(@DelegatesTo(strategy = Closure.DELEGATE_FIRST, value = MailMessageBuilder) Closure dsl) { + MailMessage sendMail(@DelegatesTo(strategy = Closure.DELEGATE_FIRST, value = MailMessageBuilder) Closure dsl) { applicationContext.getBean('mailService', MailService).sendMail(dsl) - } -} \ No newline at end of file + } +} diff --git a/src/test/groovy/grails/plugins/mail/MailMessageBuilderSpec.groovy b/src/test/groovy/grails/plugins/mail/MailMessageBuilderSpec.groovy index ca2a431c..63671a62 100644 --- a/src/test/groovy/grails/plugins/mail/MailMessageBuilderSpec.groovy +++ b/src/test/groovy/grails/plugins/mail/MailMessageBuilderSpec.groovy @@ -34,291 +34,291 @@ import javax.servlet.ServletContext */ class MailMessageBuilderSpec extends Specification implements GrailsUnitTest { - MailMessageBuilder testJavaMailSenderBuilder - MailMessageBuilder testBasicMailSenderBuilder - - private static String defaultFrom = "from@grailsplugin.com" - private static String defaultTo = "to@grailsplugin.com" - - def setup() { - def properties = new MailConfigurationProperties() - properties.default.from = defaultFrom - properties.default.to = defaultTo - - def mockJavaMailSender = Stub(JavaMailSender) { - createMimeMessage() >> new MimeMessage(Session.getInstance(new Properties())) - } - - testJavaMailSenderBuilder = new MailMessageBuilder(mockJavaMailSender, properties) - - def mockBasicMailSender = Stub(MailSender) - testBasicMailSenderBuilder = new MailMessageBuilder(mockBasicMailSender, properties) - } - - /** - * . - */ - void "Tests the basic elements of the mail DSL"() { - when: - processDsl { - to "fred@g2one.com" - subject "Hello Fred" - body 'How are you?' - } - - then: - MimeMessage msg = testJavaMailSenderBuilder.message.mimeMessage - to(msg).size() == 1 - to(msg)[0].toString() == "fred@g2one.com" - msg.subject == "Hello Fred" - msg.content == "How are you?" - } - - void "Tests that multiple recipients are added to the underlying mail message correctly"() { - when: - processDsl { - to "fred@g2one.com", "ginger@g2one.com", "grace@hollywood.com" - from "john@g2one.com" - cc "marge@g2one.com", "ed@g2one.com" - bcc "joe@g2one.com" - subject "Hello John" - body 'this is some text' - } - - then: - MimeMessage msg = testJavaMailSenderBuilder.message.mimeMessage - to(msg) == ["fred@g2one.com", "ginger@g2one.com", "grace@hollywood.com"] - cc(msg) == ["marge@g2one.com", "ed@g2one.com"] - bcc(msg) == ["joe@g2one.com"] - msg.from.size() == 1 - msg.from[0].toString() == "john@g2one.com" - msg.subject == "Hello John" - msg.content == "this is some text" - } - - void "Tests the 'headers' feature of the mail DSL. It should add the specified headers to the underlying MIME message"() { - when: - processDsl { - headers "X-Mailing-List": "user@grails.codehaus.org", - "Sender": "dilbert@somewhere.org" - to "fred@g2one.com" - subject "Hello Fred" - body 'How are you?' - } - - then: - MimeMessage msg = testJavaMailSenderBuilder.message.mimeMessage - msg.getHeader("X-Mailing-List", ", ") == "user@grails.codehaus.org" - msg.getHeader("Sender", ", ") == "dilbert@somewhere.org" - to(msg) == ["fred@g2one.com"] - msg.subject == "Hello Fred" - msg.content == "How are you?" - } - - void "Tests that the builder throws an exception if the user tries to specify custom headers with just a plain MailSender"() { - when: - processDsl(testBasicMailSenderBuilder) { - headers "Content-Type": "text/plain;charset=UTF-8", - "Sender": "dilbert@somewhere.org" - to "fred@g2one.com" - subject "Hello Fred" - body 'How are you?' - } - - then: - thrown(GrailsMailException) - } - - void "Test that default to and from fields works as expected"() { - when: - processDsl { - subject "Hello Fred" - body 'How are you?' - } - then: - MimeMessage msg = testJavaMailSenderBuilder.message.mimeMessage - to(msg)[0].toString() == defaultTo - msg.from[0].toString() == defaultFrom - } - - void "Test that envelopeFrom works as expected"() { - when: - processDsl { - to "fred@g2one.com" - from "john@g2one.com" - envelopeFrom "peter@g2one.com" - subject "Hello Fred" - body 'How are you?' - } - then: - MimeMessage msg = testJavaMailSenderBuilder.message.mimeMessage - to(msg)[0].toString() == "fred@g2one.com" - msg.from[0].toString() == "john@g2one.com" - testJavaMailSenderBuilder.envelopeFrom == "peter@g2one.com" - } - - void "Test that attachments works as expected"() { - when: - processDsl { - multipart true - to "fred@g2one.com" - subject "Hello Fred" - body 'How are you?' - attachBytes "dummy.bin", "application/binary", "abcdef".bytes - attachBytes "äöü.bin", "application/binary", "abcdef".bytes - } - - then: - MimeMessage msg = testJavaMailSenderBuilder.message.mimeMessage - msg.content instanceof MimeMultipart - 3 == msg.content.count - - and: - def attachment1 = msg.content.getBodyPart(1) - attachment1.content.text == "abcdef" - attachment1.fileName == "dummy.bin" - - and: - def attachment2 = msg.content.getBodyPart(2) - attachment2.fileName == MimeUtility.encodeWord("äöü.bin") - } - - void "Test that attaching a stream works as expected"() { - setup: - def servletContext = [getResourceAsStream: { new ByteArrayInputStream("abcdef".bytes) }] as ServletContext - - when: - processDsl { - multipart true - to "fred@g2one.com" - subject "Hello Fred" - body 'How are you?' - attach "dummy.bin", "application/binary", new ServletContextResource(servletContext, "path/to/file") - } - - then: - def msg = testJavaMailSenderBuilder.message.mimeMessage - msg.content instanceof MimeMultipart - msg.content.count == 2 - - def attachment = msg.content.getBodyPart(1) - attachment.content.text == "abcdef" - attachment.fileName == "dummy.bin" - } - - void "Test that attachment using attach file no filename override"() { - setup: "create temp file to attach" - def tempFile = File.createTempFile("grailsMailUnitTest", ".txt") - tempFile << 'abcdef' - - when: - processDsl { - multipart true - to "fred@g2one.com" - subject "Hello Fred" - body 'How are you?' - attach tempFile - } - then: - - def msg = testJavaMailSenderBuilder.message.mimeMessage - msg.content instanceof MimeMultipart - msg.content.count == 2 - - def attachment = msg.content.getBodyPart(1) - attachment.content == 'abcdef' - attachment.fileName == tempFile.name - attachment.contentType == 'text/plain' - - cleanup: - tempFile.delete() - } - - void "Test attachment using attach file with filename override"() { - setup: - def tempFile = File.createTempFile("grailsMailUnitTest", ".txt") - tempFile << 'abcdef' - - when: - processDsl { - multipart true - to "fred@g2one.com" - subject "Hello Fred" - body 'How are you?' - attach 'alternativeName.txt', tempFile - } - then: - def msg = testJavaMailSenderBuilder.message.mimeMessage - msg.content instanceof MimeMultipart - msg.content.count == 2 - - def attachment = msg.content.getBodyPart(1) - attachment.content == 'abcdef' - attachment.fileName == 'alternativeName.txt' - attachment.contentType == 'text/plain' - - cleanup: - tempFile.delete() - } - - void "Test Attach File With Non Existent File"() { - when: - processDsl { - multipart true - to "fred@g2one.com" - subject "Hello Fred" - body 'How are you?' - attach new File("I don't exist.zip") - } - then: - thrown(FileNotFoundException) - } - - @Issue("for issue GPMAIL-60") - void "test Attach Call In Beginning Of Dsl"() { - setup: - def servletContext = [getResourceAsStream: { new ByteArrayInputStream("abcdef".bytes) }] as ServletContext - - when: - processDsl { - multipart true - attach "dummy.bin", "application/binary", new ServletContextResource(servletContext, "path/to/file") - to "fred@g2one.com" - subject "Hello Fred" - body 'How are you?' - } - then: - def msg = testJavaMailSenderBuilder.message.mimeMessage - msg.content instanceof MimeMultipart - msg.content.count == 2 - msg.getHeader("To", " ") == "fred@g2one.com" - msg.getHeader("Subject", " ") == "Hello Fred" - - and: - def attachment = msg.content.getBodyPart(1) - attachment.content.text == "abcdef" - attachment.fileName == "dummy.bin" - } - - private List to(MimeMessage msg) { - msg.getRecipients(Message.RecipientType.TO)*.toString() - } - - private List cc(MimeMessage msg) { - msg.getRecipients(Message.RecipientType.CC)*.toString() - } - - private List bcc(MimeMessage msg) { - msg.getRecipients(Message.RecipientType.BCC)*.toString() - } - - private processDsl(Closure c) { - processDsl(testJavaMailSenderBuilder, c) - } - - private processDsl(MailMessageBuilder builder, Closure c) { - c.delegate = builder - c.call() - builder.finishMessage() - } + MailMessageBuilder testJavaMailSenderBuilder + MailMessageBuilder testBasicMailSenderBuilder + + private static String defaultFrom = "from@grailsplugin.com" + private static String defaultTo = "to@grailsplugin.com" + + def setup() { + def properties = new MailConfigurationProperties() + properties.default.from = defaultFrom + properties.default.to = defaultTo + + def mockJavaMailSender = Stub(JavaMailSender) { + createMimeMessage() >> new MimeMessage(Session.getInstance(new Properties())) + } + + testJavaMailSenderBuilder = new MailMessageBuilder(mockJavaMailSender, properties) + + def mockBasicMailSender = Stub(MailSender) + testBasicMailSenderBuilder = new MailMessageBuilder(mockBasicMailSender, properties) + } + + /** + * . + */ + void "Tests the basic elements of the mail DSL"() { + when: + processDsl { + to "fred@g2one.com" + subject "Hello Fred" + body 'How are you?' + } + + then: + MimeMessage msg = testJavaMailSenderBuilder.message.mimeMessage + to(msg).size() == 1 + to(msg)[0].toString() == "fred@g2one.com" + msg.subject == "Hello Fred" + msg.content == "How are you?" + } + + void "Tests that multiple recipients are added to the underlying mail message correctly"() { + when: + processDsl { + to "fred@g2one.com", "ginger@g2one.com", "grace@hollywood.com" + from "john@g2one.com" + cc "marge@g2one.com", "ed@g2one.com" + bcc "joe@g2one.com" + subject "Hello John" + body 'this is some text' + } + + then: + MimeMessage msg = testJavaMailSenderBuilder.message.mimeMessage + to(msg) == ["fred@g2one.com", "ginger@g2one.com", "grace@hollywood.com"] + cc(msg) == ["marge@g2one.com", "ed@g2one.com"] + bcc(msg) == ["joe@g2one.com"] + msg.from.size() == 1 + msg.from[0].toString() == "john@g2one.com" + msg.subject == "Hello John" + msg.content == "this is some text" + } + + void "Tests the 'headers' feature of the mail DSL. It should add the specified headers to the underlying MIME message"() { + when: + processDsl { + headers "X-Mailing-List": "user@grails.codehaus.org", + "Sender": "dilbert@somewhere.org" + to "fred@g2one.com" + subject "Hello Fred" + body 'How are you?' + } + + then: + MimeMessage msg = testJavaMailSenderBuilder.message.mimeMessage + msg.getHeader("X-Mailing-List", ", ") == "user@grails.codehaus.org" + msg.getHeader("Sender", ", ") == "dilbert@somewhere.org" + to(msg) == ["fred@g2one.com"] + msg.subject == "Hello Fred" + msg.content == "How are you?" + } + + void "Tests that the builder throws an exception if the user tries to specify custom headers with just a plain MailSender"() { + when: + processDsl(testBasicMailSenderBuilder) { + headers "Content-Type": "text/plain;charset=UTF-8", + "Sender": "dilbert@somewhere.org" + to "fred@g2one.com" + subject "Hello Fred" + body 'How are you?' + } + + then: + thrown(GrailsMailException) + } + + void "Test that default to and from fields works as expected"() { + when: + processDsl { + subject "Hello Fred" + body 'How are you?' + } + then: + MimeMessage msg = testJavaMailSenderBuilder.message.mimeMessage + to(msg)[0].toString() == defaultTo + msg.from[0].toString() == defaultFrom + } + + void "Test that envelopeFrom works as expected"() { + when: + processDsl { + to "fred@g2one.com" + from "john@g2one.com" + envelopeFrom "peter@g2one.com" + subject "Hello Fred" + body 'How are you?' + } + then: + MimeMessage msg = testJavaMailSenderBuilder.message.mimeMessage + to(msg)[0].toString() == "fred@g2one.com" + msg.from[0].toString() == "john@g2one.com" + testJavaMailSenderBuilder.envelopeFrom == "peter@g2one.com" + } + + void "Test that attachments works as expected"() { + when: + processDsl { + multipart true + to "fred@g2one.com" + subject "Hello Fred" + body 'How are you?' + attachBytes "dummy.bin", "application/binary", "abcdef".bytes + attachBytes "äöü.bin", "application/binary", "abcdef".bytes + } + + then: + MimeMessage msg = testJavaMailSenderBuilder.message.mimeMessage + msg.content instanceof MimeMultipart + 3 == msg.content.count + + and: + def attachment1 = msg.content.getBodyPart(1) + attachment1.content.text == "abcdef" + attachment1.fileName == "dummy.bin" + + and: + def attachment2 = msg.content.getBodyPart(2) + attachment2.fileName == MimeUtility.encodeWord("äöü.bin") + } + + void "Test that attaching a stream works as expected"() { + setup: + def servletContext = [getResourceAsStream: { new ByteArrayInputStream("abcdef".bytes) }] as ServletContext + + when: + processDsl { + multipart true + to "fred@g2one.com" + subject "Hello Fred" + body 'How are you?' + attach "dummy.bin", "application/binary", new ServletContextResource(servletContext, "path/to/file") + } + + then: + def msg = testJavaMailSenderBuilder.message.mimeMessage + msg.content instanceof MimeMultipart + msg.content.count == 2 + + def attachment = msg.content.getBodyPart(1) + attachment.content.text == "abcdef" + attachment.fileName == "dummy.bin" + } + + void "Test that attachment using attach file no filename override"() { + setup: "create temp file to attach" + def tempFile = File.createTempFile("grailsMailUnitTest", ".txt") + tempFile << 'abcdef' + + when: + processDsl { + multipart true + to "fred@g2one.com" + subject "Hello Fred" + body 'How are you?' + attach tempFile + } + then: + + def msg = testJavaMailSenderBuilder.message.mimeMessage + msg.content instanceof MimeMultipart + msg.content.count == 2 + + def attachment = msg.content.getBodyPart(1) + attachment.content == 'abcdef' + attachment.fileName == tempFile.name + attachment.contentType == 'text/plain' + + cleanup: + tempFile.delete() + } + + void "Test attachment using attach file with filename override"() { + setup: + def tempFile = File.createTempFile("grailsMailUnitTest", ".txt") + tempFile << 'abcdef' + + when: + processDsl { + multipart true + to "fred@g2one.com" + subject "Hello Fred" + body 'How are you?' + attach 'alternativeName.txt', tempFile + } + then: + def msg = testJavaMailSenderBuilder.message.mimeMessage + msg.content instanceof MimeMultipart + msg.content.count == 2 + + def attachment = msg.content.getBodyPart(1) + attachment.content == 'abcdef' + attachment.fileName == 'alternativeName.txt' + attachment.contentType == 'text/plain' + + cleanup: + tempFile.delete() + } + + void "Test Attach File With Non Existent File"() { + when: + processDsl { + multipart true + to "fred@g2one.com" + subject "Hello Fred" + body 'How are you?' + attach new File("I don't exist.zip") + } + then: + thrown(FileNotFoundException) + } + + @Issue("for issue GPMAIL-60") + void "test Attach Call In Beginning Of Dsl"() { + setup: + def servletContext = [getResourceAsStream: { new ByteArrayInputStream("abcdef".bytes) }] as ServletContext + + when: + processDsl { + multipart true + attach "dummy.bin", "application/binary", new ServletContextResource(servletContext, "path/to/file") + to "fred@g2one.com" + subject "Hello Fred" + body 'How are you?' + } + then: + def msg = testJavaMailSenderBuilder.message.mimeMessage + msg.content instanceof MimeMultipart + msg.content.count == 2 + msg.getHeader("To", " ") == "fred@g2one.com" + msg.getHeader("Subject", " ") == "Hello Fred" + + and: + def attachment = msg.content.getBodyPart(1) + attachment.content.text == "abcdef" + attachment.fileName == "dummy.bin" + } + + private List to(MimeMessage msg) { + return msg.getRecipients(Message.RecipientType.TO)*.toString() + } + + private List cc(MimeMessage msg) { + return msg.getRecipients(Message.RecipientType.CC)*.toString() + } + + private List bcc(MimeMessage msg) { + return msg.getRecipients(Message.RecipientType.BCC)*.toString() + } + + private void processDsl(Closure c) { + processDsl(testJavaMailSenderBuilder, c) + } + + private void processDsl(MailMessageBuilder builder, Closure c) { + c.delegate = builder + c.call() + builder.finishMessage() + } }