grails / grails-mail

The Grails Mail Plugin
https://grails.github.io/grails-mail/
Apache License 2.0
14 stars 25 forks source link

Dynamic parameters. #18

Open kuez opened 7 years ago

kuez commented 7 years ago

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

helgew commented 7 years ago

You beat me to it! 👍 I posted in the slack #plugin channel yesterday with a similar business requirement to see if there had been any discussions or efforts on implementing this. It is mentioned as a TODO in the documentation.

I would be motivated to take this on but think it would be best if the authors pitch in with their thoughts on how this should be implemented.

Currently, the mail sender is a bean created in the plugin class and injected in the MailMessageBuilderFactory, which in turn creates a builder for every message sent. Options for implementing a more flexible configuration of dynamically configured servers could include

Thoughts? Other options/preferences?

helgew commented 7 years ago

In the absence of any feedback so far, I have been able to implement a workaround by replacing the mailMessageBuilderFactory bean with the following:

import grails.config.Config
import grails.core.GrailsApplication
import grails.plugins.mail.MailMessageBuilder
import org.springframework.mail.MailSender
import org.springframework.mail.javamail.JavaMailSenderImpl

import javax.mail.Session
import java.security.Security

class MailMessageBuilderFactory extends grails.plugins.mail.MailMessageBuilderFactory {

    GrailsApplication grailsApplication

    @Override
    MailMessageBuilder createBuilder(Config config) {
        MailSender mailSender = this.mailSender
        if (config.props) {
            mailSender = getMailSender(config)
        }
        new MailMessageBuilder(mailSender, config, mailMessageContentRenderer)
    }

    MailSender getMailSender(config) {
        JavaMailSenderImpl mailSender = new JavaMailSenderImpl()
        if (config.host) {
            mailSender.host = config.host
        } else if (!config.jndiName) {
            def envHost = System.getenv()['SMTP_HOST']
            if (envHost) {
                mailSender.host = envHost
            } else {
                mailSender.host = "localhost"
            }
        }

        if (config.encoding) {
            mailSender.defaultEncoding = config.encoding
        } else if (!config.jndiName) {
            mailSender.defaultEncoding = "utf-8"
        }

        if (config.port) {
            mailSender.port = config.port
        }

        if (config.username != null) {
            mailSender.username = config.username
        }

        if (config.password != null) {
            mailSender.password = config.password
        }

        if (config.protocol != null) {
            mailSender.protocol = config.protocol
        }

        if (config.props instanceof Config) {
            Session session = Session.getInstance(config.props.toProperties())
            session.setDebug(config.debug ?: false)
            mailSender.session = session
        }

        mailSender
    }
}

Basically, the above relies on the config object to contain a key props when the mailService.sendMail(config) { ... } method is used. Seems a bit hackish, but it works.

That was the easy part... figuring out how to use XOAUTH2 with a service account user for Google Apps, not so much :)