How to send an email in grails - grails

My app wants to send an email using the custom mailers. I went through the doc http://grails.org/Mail+from+Grails which I find pretty incomplete. I followed the steps mentioned in the alternative mailer, but I get an exception
NullPointerException occurred when processing request: [GET] url/sendEmail
Cannot invoke method sendNewEmail() on null object.
My controller looks like this
XXXMailer paMailer
paMailer.sendNewEmail()

The web page you linked to is merely a proposal which may have never been implemented and hasn't been updated in 3 years. The most popular way to to send email from a Grails app is with the mail plugin. The docs are comprehensive, and it's very easy to use.

XXXMailer seems to be a service, or any other automatically wired thing. So, you have to define it as field, and only then used it from an method, like:
class MyController {
XXXMailer paMailer //now it will be filled with real instance
def myAction() {
paMailer.sendNewEmail()
}
}

Related

Rails - Logging events with tags or types and getting an email alert - best practices?

Wondering if someone could offer some best practice on logging techniques they use and maybe tagging certain events using airbrake or newrelic or loggly, or something of that nature?
For example, lets say I have events that should never hit my controller in theory, because they are protected on the front end - like a regular user being able to manage an admin. I prevent these controls from being outputted on the front end using ruby if statements. So if my controller gets hit with a request like this, then I know that either that code isn't working right, or someone is doing some hacking with the request being sent.
Either way I want to know. I just found myself writing:
#TODO: Log this. Either the front end is broken or the user is sending hacked requests
Wondering if anyone can offer some insight as to how they handle it, maybe with a third party logging tool, maybe with some sort of tag that I could set up email alerts with said tool?
Morgan from Airbrake here. We don't have tagging for Airbrake Exceptions.
One way to solve this with our service is to send a custom error to Airbrake from your controller.
The error will trigger an Airbrake notification email and you will be notified.
For Example:
# find me in app/controllers/some_controller.rb
# custom error
class ControllerAccessError < StandardError
end
def action
...
msg = 'front end is broken or the user is sending hacked request'
e = ControllerAccessError.new(msg)
Airbrake.notify_or_ignore(e)
end
Here is some more info on manually sending errors to airbrake with ruby:
https://github.com/airbrake/airbrake/wiki/Using-Airbrake-with-plain-Ruby
Jason from Loggly here. You can also setup a new Logger and then log anything you like. This uses pure Ruby code without any proprietary libraries. For example:
logger.warn("Regular user should not have access")
Even better, you can use JSON fields to make for easy reporting and filtering. I'm not a Ruby programmer, but I think it'd look something like this?
logger.warn({:username => username, :type => "Access Violation", :message => "Regular user should not have access"}.to_json);
In Loggly, you can setup alerts to be sent over email whenever you get a message matching this search
json.type:"Access Violation"

Proper way to handle GORM calls in TagLib

I started using Webflow on a Grails 2.2.4 project today and I immediately ran into the following exception:
could not initialize proxy - no Session
Doing some research I ran across this SO question which then led me to this JIRA issue that is marked as Won't Fix because making GORM calls in a TagLib is considered a bad idea.
Since this kind of stuff seems to work fine from regular actions, I've not run across the issue before. My question is, how should the following code be structured so that I'm following the right practice.
I have a template called _nav.gsp which handles my sites navigation bar. There are a lot of menu options that are shown and hidden depending on user's roles. I have the following in a TagLib:
def ifProjectGranted = { attr, body ->
def authenticatedUser = docRegService.authenticatedUser
if (authenticatedUser) {
def roles = UserRole.findAllByUser(authenticatedUser).collect { it.role.authority }
// here I check roles and manage my rendering to the output
}
}
I know I can solve the problem by wrapping my findAllByUser in a withTransaction block. But according to the JIRA, I shouldn't be doing this lookup at all here. So where would I do it?

Using the Mailgun HTTP api from Rails3

We are working on changing a Rails 3.2 app to use the Mailgun http api for handling email campaigns. Currently we are using ActionMailer for building out our templates and sending over smtp but since we want to use some of the more advanced features offered by Mailgun we would rather not deal with all the MIME headers and instead use the REST api.
To render our haml template as a string for the HTTP POST it looks like we either need to use some sort of controller or commit a 'design smell' and invoke the action view from within a model. Being that the email will be executed by a background worker it doesn't really make sense to call it from a controller; is there some other method that we are missing?
I wrote a Rails Action Mailer adapter for mailgun. This means you can use the standard Rails approach for sending emails and you don't have to invent a custom wrapper for doing it.
Regards
From Haml doc:
template = File.read('path_to/your_haml_file')
haml_engine = Haml::Engine.new(template)
your_variables = { }
html = haml_engine.render(Object.new, your_variables)

Rails how to handle error and exceptions in model

So I'm parsing data from twitter api in rails using the twitter library, and sometimes the response from api might be like this:
{
error: "Invalid parameter"
}
And the model will raise an exception, right now I'm silently catch it and put the error.message into the log, how do I pass this exception to the controller so I can display it on the view? Thanks.
UPDATE:
The error is likely to happen because I'm allowing my customer to build queries, and they might put advanced queries like "https://search.twitter.com/search.json?since_id=1&&q=near:NYC%20within:15mi" which is supported by the twitter webpage but not by it's API. So I want to catch these kinda of error and display a flash message so the user can have some feedback.
I guess you could an attr_accessor. Something like twitter_errors.
In your model:
attr_accessor :twitter_errors
begin
#your twitter code here
rescue
self.twitter_errors = "whatever"
end
And in your controller, set the flash if #model.twitter_errors isn't empty.
The typical way is to use ActiveModel::Errors.
ActiveRecord uses this mixin extensively for validations. So in an ActiveRecord object you have access to errors.add(:base, TwitterError.to_s). You can use this to set the error when it is caught. And then you should be able to access it via the controller/view using ar_object.errors.
(There are already some helpers for displaying errors like this the docs have much more info)

Forward a mail using Tmail & ActionMailer::ARMailer

I'm writing a rake task to go through one of our mailboxes of incoming mail, using Tmail. For certain mails, i just want to forward them on to another address. I'm not sure what the best way to do that is though.
Our regular mails for the website are sent out using ARMailer: i call Mailer.deliver_ and the mail is generated from a template and put into our Email table, which in accessed by ARMailer which actually sends the mails out. So, the class definition of my Mailer class looks like this:
class Mailer < ActionMailer::ARMailer
#list of methods here, one per email type
end
So, what i want to do, is, in my script when i have a Tmail object representing the incoming mail, is to generate a new mail to stick into our mail queue which is basically the Tmail mail, forwarded onto a new address. I'm not sure what the best way to do that is. I could build up a new multipart mail copying the body, subject and from field from the recieved Tmail object, but that seems like it might be a bit clumsy, and that there should be a nicer way.
Can i do something like
newmail = Mailer.create_forward(my_tmail_object)
newmail.to = "forwardingaddress#domain.com"
newmail.deliver
??
Mailer/ARMailer doesn't have the create_forward method but it's something like that that i'm after. Any advice welcome! thanks

Resources