0

I'm trying to make a simple contact us form so I need to implement the mailer.

I created a controller:

class ContactusController < ApplicationController
   def index
      @contact_us = Contactus.new
   end

   def new
      redirect_to(action: 'index')
   end

   def create
      @contact_us = Contactus.new(params[:contactus])
      if @contact_us.deliver
         flash[:notice] = "Thank-you, We will contact you shortly."
      else
         flash[:error] = "Oops!!! Something went wrong. Your mail was not sent."
      end
      render :index
    end
 end

As I don't want to save the data I used ActiveModel:

class Contactus
   extend ActiveModel::Naming
   include ActiveModel::Conversion
   include ActiveModel::Validations
   include ActionView::Helpers::TextHelper
   attr_accessor :name, :email, :message

   validate :name,
       :presence => true

   validates :email,
        :format => { :with => /\b[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}\z/ }

   validates :message,
        :length => { :minimum => 10, :maximum => 1000 }

   def initialize(attributes = {})
      attributes.each do |name, value|
          send("#{name}=", value)
      end
   end

   def deliver
       return false unless valid?
   mail(
        :to => "XXXXXXXX@gmail.com",
        :from => %("#{name}" <#{email}>),
        :reply_to => email,
        :subject => "Website inquiry",
        :body => message,
        :html_body => simple_format(message)
       )
   true
 end

 def persisted?
     false
 end
end

Everything works fine. The routing is good, the validation works, but the only error I get is: undefined method mail for #<Contactus:0x007f9da67173e8>

I tried to make mailer with name Contactus and user Model code in that, but I got the following error: private method new used

How can I use the ActionMailer function in ActiveModel?

Mischa
  • 42,876
  • 8
  • 99
  • 111
Dinkar Thakur
  • 3,025
  • 5
  • 23
  • 35

2 Answers2

2

To be a bit more verbose of how to set up the mailer, run this command to generate your mailer:

rails generate mailer ContactMailer

add the following to a file named app/mailers/contact_mailer

class ContactMailer < ActionMailer::Base
  default from: #{from_email}

  def contact_mail(contact)
    @contact = contact
    mail(to: #{email}, subject: #{Whatever your subject would be})
  end
end

ActionMailer uses views to render the layouts of its messages. I checked the documentation, but I couldn't find anything on the html_body option you're using here. Maybe try removing that and using body: simple_format(message) or just create the template app/views/mailers/contact_mailer/contact_mail.html.erb and put the message in yourself. You can see I made @contact an instance variable on purpose, so if I were to create such a template, I'd have access to all available attributes of the object, so you could customize a bit further if you wanted to.

On a different note...

I'm a little concerned that you're forwarding the new action to the index action here. Do you have a really good reason to be changing the RESTful approach? 9 times out of 10, when I've had strange problems with private method called or some other cryptic error, it's been when I was trying to cheat the system. If you reassign the new action to create the new Contactus object, does that fix your problem?

Update for SMTP settings

My employer's standard for these settings may not be the best out there, but here's what I've done so far. In my environments/production.rb

config.action_mailer.raise_delivery_errors = false
config.action_mailer.perform_deliveries = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
  :hash => 'of',
  :mail => 'client',
  :smtp => 'settings'
}

In my environments/development.rb I copy the same block, but replace the first line with

config.action_mailer.raise_delivery_errors = true

In my environments/test.rb I add none of the above. Instead, I add this line

config.action_mailer.delivery_method = :test

but that's because I like to test that the emails get sent in my RSpec tests.

I'm not sure what your configs look like in your environment.rb, but you may want to make sure you're configuring through ActionMailer like this. Naturally, restart your app after making these changes and see if you still have authentication problems.

For particular authentication problems

My personal SMTP settings authenticate through gmail, so my settings in these files include the following pairs:

:address => 'smtp.gmail.com',
:port => #{port_number},
:domain => #{our_email_domain},
:authentication => 'plain',
:enable_starttls_auto => true

Try looking up your port and domain. A google search should suffice if you're not doing this for a business with its own domain. The authentication and smarttls settings should help if your password just isn't being interpreted correctly.

Brad Rice
  • 1,334
  • 2
  • 17
  • 36
  • i'll try it for sure, about the new action problem i found that i was creating an object of mailer class but infact it have no construtor so there was the problem :) – Dinkar Thakur Jul 06 '13 at 17:20
  • now i'm a bit forward but now getting very strange errro Net::SMTPAuthenticationError even though i entered right things in ActionMailer::Base.smtp_settings in enviornment.rb any clue about that – Dinkar Thakur Jul 06 '13 at 17:42
  • Give me a couple minutes. I'll update my answer with some details. – Brad Rice Jul 06 '13 at 17:59
  • i figure out the problem. i was using gmail and they need user to have device specific password or domain specific i create a password for my mac and it work fine i recieve the mail. But getting error on production mode on heroku :( . Where we have to put the smpt configuration in rails 4 in production.rb or enviornment.rb?? – Dinkar Thakur Jul 06 '13 at 18:10
  • i figure that out it saysJul 06 11:45:14 weblabsolution app/web.1: I, [2013-07-06T18:39:37.037813 #2] INFO -- : Completed 500 Internal Server Error in 425ms Jul 06 11:45:14 weblabsolution app/web.1: F, [2013-07-06T18:39:37.042030 #2] FATAL -- : Jul 06 11:45:14 weblabsolution app/web.1: Net::SMTPAuthenticationError (535 Authentication failed: Bad username / password but i'm entering right username and password – Dinkar Thakur Jul 06 '13 at 18:58
  • That might happen if you're not giving it right host or address that would recognize the username/password. Check my answer for an update soon. – Brad Rice Jul 06 '13 at 19:03
1

You have to create a separate class in app/mailers that inherits from ActionMailer::Base. In that class you can call the mail method. You cannot call mail directly in your ContactUs class.

Once you have setup your mailer class can use it like this in ContactUs:

ContactMailer.contact_mail(self).deliver
Mischa
  • 42,876
  • 8
  • 99
  • 111
  • i used ActionMailer::Base.mail( :to => "xxxxxxxx@gmail.com", :from => %("#{name}" <#{email}>), :reply_to => email, :subject => "Website inquiry", :body => message, :html_body => simple_format(message) ) and it worked but not getting the mails though i'm getting success message, WHY SO?? – Dinkar Thakur Jul 06 '13 at 16:03
  • can you be more precise what to do step wise.. sorry novice here :( – Dinkar Thakur Jul 06 '13 at 16:05