1

I am trying to send an email from a grails app. I tried with recommended settings using gmail and it worked fine. I sent mail successfully. But I want to override the username and password dynamically. I don't know how can I do it. Can anybody help?

    grails {
    mail {
        host = "smtp.gmail.com"
        port = 465
        username = "faruq@gmail.com"    // Want to change dynamically like variable ${branch.mail}
        password = "12345"              // Want to change dynamically like variable ${branch.pass}
        props = [
            "mail.smtp.auth":"true",
            "mail.smtp.socketFactory.port":"465",
            "mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
            "mail.smtp.socketFactory.fallback":"false"
        ]
    }
}

I use this process for overriding the username from the controller

grailsApplication.config.grails.mail.username = Branch.get(2).mail

by this process username successfully changes

here Branch is my domain class and mail is property

but an authentication problem comes up:

javax.mail.AuthenticationFailedException: 535-5.7.8 Username and Password not accepted

Now what can I do?

Noam Hacker
  • 4,671
  • 7
  • 34
  • 55
Omar Faruq
  • 1,220
  • 2
  • 12
  • 29
  • When you say 'dynamically' do you mean based on the deployment site (e.g. companyA, companyB, etc) or based on domain instances (e.g. userX in my system uses Gmail, so send his email through Gmail, userY uses Yahoo, so send his email through Yahoo, etc)? – dspies Sep 24 '13 at 16:28
  • yes i also want this(if possible) – Omar Faruq Sep 25 '13 at 03:45

3 Answers3

1

You can use an external configuration file - put placeholder values in the main Config.groovy

grails {
    mail {
        host = "smtp.gmail.com"
        port = 465
        username = "<changeme>"
        password = "<changeme>"
        props = [
            "mail.smtp.auth":"true",
            "mail.smtp.socketFactory.port":"465",
            "mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
            "mail.smtp.socketFactory.fallback":"false"
        ]
    }
}

and then override them with the correct values in the external config:

grails {
  mail {
    username = "faruq@gmail.com"
    password = "12345"
  }
}

To be able to change the credentials dynamically at run time it gets rather more complicated. Under the covers the mail plugin creates a Spring bean which is an instance of JavaMailSenderImpl to handle the actual sending of emails, and this bean is configured by default with static settings from the config. But at runtime this class appears to call its own getUsername() and getPassword() every time it needs to send a message. So you could replace this bean with your own custom subclass of JavaMailSenderImpl that overrides these methods to pull the details from the request context (code example, not tested, and imports/error handling omitted):

src/groovy/com/example/RequestCredentialsMailSender.groovy

class RequestCredentialsMailSender extends JavaMailSenderImpl {
  public String getUsername() {
    return RequestContextHolder.requestAttributes?.currentRequest?.mailUsername ?: super.getUsername()
  }

  public String getPassword() {
    return RequestContextHolder.requestAttributes?.currentRequest?.mailPassword ?: super.getPassword()
  }
}

You'd have to register this bean in your resources.groovy, and duplicate a fair bit of the configuration from the mail plugin itself, which is less than ideal:

grails-app/conf/spring/resources.groovy

beans = {
  mailSender(com.example.RequestCredentialsMailSender) {
    def mailConf = application.config.grails.mail
    host = mailConf.host
    port = mailConf.port
    username = mailConf.username // the default, if not set in request
    password = mailConf.password
    protocol = mailConf.protocol
    javaMailProperties = mailConf.props
  }
}

Now when you need to send mail from a controller you can do

request.mailUsername = Branch.get(2).mail
request.mailPassword = Branch.get(2).mailPassword
sendMail { ... }
Ian Roberts
  • 120,891
  • 16
  • 170
  • 183
0

Just wanted to verify Ian's answer and expand it.

In the default Config.groovy file I have the added external config line:

 grails.config.locations = [
     "file:./${appName}-config.groovy",
     "classpath:${appName}-config.groovy"
     ]

....
// and here is the mail config as above
grails{
    mail{
.... 

In the config file at the root level I have my config file: TestApp-config.groovy (where TestApp is the name of my app) as above:

grails {
  mail {
    username = "faruq@gmail.com"
    password = "12345"
  }
}

Didn't need anything past this and it worked great.

Nathan Dunn
  • 447
  • 5
  • 16
0

We can also use replyTo field if our aim is only to get the reply back on specific Email Id. We can dynamically pass an email id to "replyTo" field and can expect an email back on the same.

Example :

asynchronousMailService.sendMail { to ["xyz@gmail.com","pqr@gmail.com"] subject "Subject Text" if(ccs) cc ["xyz1@gmail.com","pqr1@gmail.com"] if(bccs) bcc ["xyz2@gmail.com","pqr2@gmail.com"] if(replyTo) replyTo "xyz@gmail.com" if(attachBytes) attachBytes attachBytes } NOTE: Adding "replyTo" will only allow us to get the emails back on the specified email-id and will not send the email from the configured email.

It was suitable in my use case. Hope it helps !

Vaibhav Sharma
  • 129
  • 2
  • 5