How to send mail from a Domain/Service in Grails - grails

I have this plugin installed, I want to send mails from a Service/Domain class method , I was doing like this
class TrainingService {
def mailService
public def sendMail() {
mailService.sendMail {
multipart true
to "abc#xyz.com"
subject "Hello,"
body 'How are you?'
}
}
I got error "Cannot invoke method sendMail() on null object", How to resolve this

I am missing the "from" attribute and if you're using multipart email, you should also fill in additional parts of the email, snippet from my code:
mailService.sendMail {
multipart true
from '"Some account" <someaccount#email.com>'
to 'anotheremail#somedomain.com'
bcc emailAddresses.toArray()
subject dto.title
body emailPart1
html g.render(
template: 'emailNotification',
model: [ name: dto.name ]
)
}

Have you configured your SMTP server. You need these entries in your config file for mail to work. Do you have these ?
grails {
mail {
host = "hostname"
pop_port = 25
username = "username"
password = "password"
type = "pop3"
}
}
you can find more information about the configuration here

I got this error when I was passing variables called 'from' and 'to' into the method that was using sendMail. Try renaming the sendMail method and making sure that you don't have any conflicting variable names.

Related

I have a problem with Jenkins Pipeline script. No such property for class WorkFlowScript

When I create new job, results of this job jenkins send on emails of all teams, but when we create test job(we can understand it by name of job), we should send email only to creator of job.
It was so and it works:
pipe(..){
timeout(..){
BuildEmailExt email = new BuilEmailExt(this, Emails.allTeams())
someCode..
}
}
Then i add if:
pipe(..){
timeout(..){
if(env.JOB_NAME =~ /somePattern/){
BuildEmailExt email = new BuilEmailExt(this, SENDER)
}
else{
BuildEmailExt email = new BuilEmailExt(this, Emails.allTeams())
}
someCode..
}
}
And I get Exception : No such property email for class: WorkFlowScript
What am I doing wrong?
By defining the variable inside the if and else, it doesn't exist outside of that scope, so is not accessible outside of the conditional.
You can move the definition outside of the if, and then set it like so:
pipe(..){
timeout(..){
BuildEmailExt email
if(env.JOB_NAME =~ /somePattern/){
email = new BuilEmailExt(this, SENDER)
}
else {
email = new BuilEmailExt(this, Emails.allTeams())
}
someCode..
}
}
You could also do this which may look cleaner (ymmv)
pipe(..){
timeout(..){
BuildEmailExt email = new BuilEmailExt(this, (env.JOB_NAME =~ /somePattern/) ? SENDER : Emails.allTeams())
someCode..
}
}

full email validation on Meteor using Mandrill

I have read several SO posts about using Mandrill with Meteor.js for email validation, yet I've found a problem no others seem to face.
Ultimately, I want the verified property of a user to be set to true after clicking the email validation url. I am using Mandrill to send customized email templates containing a verification_url. I have the accounts-password and accounts-ui packages added. My code looks like this:
if (Meteor.isServer) {
Meteor.startup(function () {
Mandrill.config({
username: process.env.MANDRILL_API_USER,
key: process.env.MANDRILL_API_KEY
// port: 587, // defaults to 465 for SMTP over TLS
// host: 'smtp.mandrillapp.com', // the SMTP host
// baseUrl: 'https://mandrillapp.com/api/1.0/' // update this in case Mandrill changes its API endpoint URL or version
});
Accounts.config({
sendVerificationEmail: true
});
Accounts.emailTemplates.verifyEmail.html = function (user, url) {
var referralCode = Random.id();
var result;
try {
result = Mandrill.templates.render({
template_name: 'email-verification',
template_content: [],
merge_vars: [
{
name: 'SUBJECT',
content: 'my fancy subject'
},
{ name: 'EMAIL',
content: 'my fancy email'
},
{
name: 'VERIFICATION_URL',
content: 'http://localhost:3000/?ref=' + referralCode
}
]
});
} catch (error) {
console.error('Error while rendering Mandrill template', error);
}
return result.data.html;
};
});
When I create a user the verification email is correctly sent, however when I click the verification link within the email, nothing is done on the server, i.e. I look at my app's MongoDB and see on the user document still have the property verified: false. I've tried to work with onEmailVerificationLink (http://docs.meteor.com/#/full/Accounts-onEmailVerificationLink) but I get an error in the console saying onEmailVerificationLink has already been called, which happens because accounts-ui is apparently calling it for me. How do I do proper email verification in Meteor.js using Mandrill?
Finally figured it out. Instead of the line
content: 'http://localhost:3000/?ref=' + referralCode
I should replace it with
content: url
since Meteor is already creating the validation url for me, and passing it in through the "url" argument of the function. Clearly I didn't need referralCode either

Using facebook social plugin how to get email address in grails

I want to get email address using social plugin of grails . I am using facebook plugin compile ':spring-security-oauth-facebook:0.1' and configured properly in Config.groovy like below.
oauth {
debug = true
providers {
facebook {
api = org.scribe.builder.api.FacebookApi
key = 'here is my-key'
secret = 'my-secret-key'
successUri = '/oauth/facebook/success'
failureUri = '/oauth/facebook/failure'
callback = "${baseURL}/oauth/facebook/callback"
scopes = "email"
}
}
}
After get successfully response, below method is called.
def onSuccess(String provider) {
if (!provider) {
log.warn "The Spring Security OAuth callback URL must include the 'provider' URL
parameter"
throw new OAuthLoginException("The Spring Security OAuth callback URL must include the
'provider' URL parameter")
}
def sessionKey = oauthService.findSessionKeyForAccessToken(provider)
if (!session[sessionKey]) {
log.warn "No OAuth token in the session for provider '${provider}'"
throw new OAuthLoginException("Authentication error for provider '${provider}'")
}
}
OAuthToken oAuthToken = springSecurityOAuthService.createAuthToken(provider,
session[sessionKey])
println "oAuthToken.principal = "+oAuthToken.principal.toString();
println "oAuthToken.socialId = "+oAuthToken.socialId;
println "oAuthToken.properties= "+oAuthToken.properties
println "oAuthToken.properties= "+oAuthToken.name
println "oAuthToken.properties= "+oAuthToken.toString();
How to get email address by using this. I successfully get response from facebook but it is same number for Username,socialId,profileId but i need email Address like myemailid#gmail.com
please help me.

Grails2.1 Dynamic mail configuration

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?
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 { ... }
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.
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 !

how to integration test email body in a Grails Service that uses the Mail plugin

I am attempting to write integration tests for a Grails service that does, among other things, send email via the excellent Mail Plugin. I can disable the actual sending of email via configuration, which is great, but I would like to verify that the parameters are correct body is being rendered correctly, or at very least that the method has been called when I expect. As per the documentation, the full path to GSP for the body must be supplied.
As part my test I'd like to do something like this - is there a way to access the email body and other parameters programmatically after sending?
sendMail {
to myemailparams.to
subject myemailparams.subject
body( view:"/emailviews/someemailview",
model:[contentparam: myemailparams.somecontentvalue)
}
//verify correct sending to and subject parameters, and that body contains correct contentvalue
//or at least that the method has been called (Mock it out?)
Note I realize that I can encapsulate the testing of the email body rendering into a separate isolated test that doesn't involve the mail plugin. But the purpose of this integration test is to ensure a lot of things, including the email send, happen correctly upon call to the service method. I would even be satisfied with an answer that describes how to mock the service, and a check that verifies 'sendMail' has been called when expected.
You can override the sendMail method using metaClass and then do some checking to ensure that sendMail was called:
void testSendMail() {
MyClass myClass = new MyClass()
def sendMailCalled = false
myClass.metaClass.sendMail = { Closure c->
sendMailCalled = true
}
myClass.functionThatCallsSendMail()
assert sendMailCalled
}
Here is an example of how I assert things that were sent to MailService:
def setup(){
mailParams = [:]
mockMailService.ignore.sendMail{ callable ->
messageBuilder = new MailMessageBuilder(null, new ConfigObject())
messageBuilder.metaClass.body = { Map params ->
mailParams.body = params
}
messageBuilder.metaClass.async = { Boolean param ->
mailParams.async = param
}
messageBuilder.metaClass.to = { String param ->
mailParams.to = param
}
messageBuilder.metaClass.subject = { String param ->
mailParams.subject = param
}
callable.delegate = messageBuilder
callable.resolveStrategy = Closure.DELEGATE_FIRST
callable.call()
}
service.mailService = mockMailService.proxyInstance()
}
Then, In my test, after executing the method that sends mail, I assert this way (Spock syntax for assertions):
then:
mailParams.to == 'test#test.com'
mailParams.async == true
mailParams.subject == 'fnuser.billingEmail.subject{}en'
mailParams.body.view == '/mailtemplates/setBillingEmail'
mailParams.body.model.destinationUrl == "myDestinationUrl"
mailParams.body.model.logoUrl == 'myUrl/templatelogo.png'
mailParams.body.model.locale == Locale.ENGLISH

Resources