I have three mailers, all of which work. But for one (the contact form) the mailer preview doesn't work and I don't understand why.
The error message:
undefined method 'email'
def new_message(message)
#message = message
mail from: message.email, subject: "Message from #{message.name}"
end
In app/mailers/message_mailer.rb I have:
class MessageMailer < ApplicationMailer
default to: "<info#myemail.com>",
return_path: "<info#myemail.com>"
def new_message(message)
#message = message
mail from: message.email, subject: "Message from #{message.name}"
end
end
Part of app/views/messages/new.html.erb:
<%= form_for :message, url: contact_path do |f| %>
<%= f.label :name %>
<%= f.text_field :name, placeholder: 'Name', class: 'form-control' %>
<%= f.label :email %>
<%= f.email_field :email, placeholder: 'Email', class: 'form-control' %>
<%= f.label :content %>
<%= f.text_area :content, placeholder: 'Your message…', class: 'form-control' %>
<%= f.submit "Send", class: "btn btn-primary" %>
<% end %>
test/mailers/previews/test_mailer_preview.rb:
class MessageMailerPreview < ActionMailer::Preview
message = [name: "My Name", email: "noreply#example.com", content: "This is my message"]
MessageMailer.new_message(message)
end
end
The contact form is properly working on the development server, and the other two mailers (password reset and authentication) also work and for these last two mailers the previews also work properly. These two mailers also have model.email in the mailer, and there it does work. I don't understand why the preview for the contact form mailer produces the error message.
I turns out that if I replaced
message = [name: 'My Name', email: 'noreply#example.com', content: 'This is my message']
with
message = Message.first
message.email = "example#example.com"
or even just
message = Message.first
the preview does work. Don't understand why since I would expect the original formulation also to work.
Your mailer class isn't inherited from ActionMailer, which is fine if you have an ApplicationMailer class doing that already, can you post the code for it please? Otherwise try this.
class MessageMailer < ActionMailer::Base
Related
I'm trying to build my first contact form, that would send someone's name, email and message to my email address to me. I've seen quite a lot of tutorials and answered questions on stackoverflow, but it didn't help me to fix the problem I'm having. I know it has something to do with the routing but I can't figure what and why.
I'm getting the following error:
Routing Error
uninitialized constant ContactController
Here are my files :
routes.rb
match '/send_mail', to: 'contact#send_mail', via: 'post'
match '/mail', to: 'contact#contact', via: 'get'
controllers/contacts_controller.rb
def send_mail
name = params[:name]
email = params[:email]
body = params[:comments]
ContactMailer.contact_email(name, email, body).deliver
redirect_to contact_path, notice: 'Message sent'
end
mailers/contact_mailer.rb
class ContactMailer < ActionMailer::Base
default to: 'mymail#gmail.com'
def contact_email(name, email, body)
#name = name
#email = email
#body = body`enter code here`
mail(from: email, subject: 'Contact Request')
end
end
views/contact.html.twig
<div class="container-content">
<div class="container">
<%= form_tag(send_mail_path) do %>
<div class="form-group">
<%= label_tag 'name', 'Name' %>
<%= text_field_tag 'name', nil, class: 'form-control', placeholder: 'John Doe' %>
</div>
<div class="form-group">
<%= label_tag 'email', 'Email' %>
<%= email_field_tag 'email', nil, class: 'form-control', placeholder: 'johndoe#domain.com' %>
</div>
<div class="form-group">
<%= label_tag 'comments', 'Comments' %>
<%= text_area_tag 'comments', nil, class: 'form-control', rows: 4, placeholder: 'How can I help you?' %>
</div>
<%= submit_tag nil, class: 'btn btn-default btn-about' %>
<% end %>
</div>
</div>
views/contact_email.html.erb
<!DOCTYPE html>
<html>
<head>
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<p>Mail received from <%= "#{ #name } (#{ #email }):" %></p>
<p><%= #body %></p>
</body>
</html>
config/initializers.rb
module Contact
class Application < Rails::Application
config.action_mailer.delivery_method = :sendmail
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.active_record.raise_in_transactional_callbacks = true
end
end
initializers/stmp_config.rb
config.action_mailer.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => "gmail.com",
:user_name => "mymail#gmail.com",
:password => "password",
:authentication => :login,
:enable_starttls_auto => true
}
As I'm newbie in the rails world, I'm not sure at all of what I'm doing, but I've seen a lot of tutorials where people had a code similar to mine, but no one seems to have this problem
Where did i go wrong ?
Thank you in advance
You may want to change your routes.rb as follows (contacts instead of contact):
match '/send_mail', to: 'contacts#send_mail', via: 'post'
match '/mail', to: 'contacts#contact', via: 'get'
Thats one way to create a contact form - however its not really a Rails app. Its just an app that happens to be using Rails.
This is how you can use the Rails conventions to make this more robust and less messy.
Model
Lets generate a model and migration:
$ rails g model enquiry name:string email:string body:text
Then we run the migration:
$ rake db:migrate
So why create a model if we are just sending an email? Because email fails. And you don't want to lose important enquiries from potential customers.
We also want our model to validate that the user provides the required fields:
# app/models/enquiry.rb
model Enquiry < ActiveRecord::Base
validates_presence_of :name, :email, :body
validates_format_of :email, with: /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
end
Controller
Lets create a RESTful route:
# config/routes.rb
# ...
resources :enquiries, only: [:new, :create]
Note that we are calling it enquiries. Instead of using an procedure oriented send_contact route we have the resource enquiries which gives us conventions for how to show, create and update it.
You can see what routes are generated with $ rake routes.
See Resource Routing: the Rails Default.
Lets create a controller for our new route:
# app/controllers/enquiries_controller.rb
# note controllers use the plural form
class EnquiriesController < ApplicationController
# GET '/enquiries/new'
def new
#enquiry = Enquiry.new
end
# POST '/enquiries'
def create
#enquiry = Enquiry.new(enquiry_params)
if #enquiry.save
ContactMailer.contact_email(name, email, body).deliver
redirect_to root_path, success: 'Thanks for getting in touch, we will look into it ASAP.'
else
render :new
end
end
private
def enquiry_params
params.require(:enquiry).permit(:name, :email, :body)
end
end
View
We also need a form:
# app/views/enquiries/new.html.erb
<%= form_for(#enquiry) do |f| %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :name %>
</div>
<div class="form-group">
<%= f.label :body %>
<%= f.text_area :body %>
</div>
<%= f.submit %>
<% end %>
By using a form builder and a model our form will automatically "play back" the values if the user submits an invalid form.
Your problem in 'ContactController' - it's must be in plural: 'ContactsController'!
I'm using careerfoundry's tutorial on using Sendgrid to send emails with Heroku. I'm using their exact code for the user mailer and thank_you action in the pages controller. This code is working for the most part. The issue is that the subject line I receive in my inbox is this:
A new contact form message from #{name}
User_Mailer.rb
class UserMailer < ActionMailer::Base
default from: "from#example.com"
def contact_form(email, name, message)
#message = message
mail(:from => email,
:to => 'your-email#example.com',
:subject => "A new contact form message from #{name}")
end
end
Contact Form
<%= form_tag("/thank_you") do %>
<div class="row">
<div class="col-md-4">
<div class="input-group">
<%= text_field_tag :name, nil, class: 'form-control', placeholder: 'Name' %>
</div>
</div>
<div class="col-md-8">
<div class="input-group">
<span class="input-group-addon" id="basic-addon1">#</span>
<%= text_field_tag :email, nil, class: 'form-control', placeholder: 'Email' %>
</div>
</div>
</div>
<br>
<div class="row">
<div class="col-md-12">
<div class="input-group text-area-wide">
<%= text_area_tag :message, nil, class: 'form-control text-area-wide', placeholder: 'Message' %>
</div>
</div>
</div>
<br>
<%= submit_tag 'Send Message', class: 'btn btn-success' %>
<% end %>
Pages Controller
def thank_you
#name = params[:name]
#email = params[:email]
#message = params[:message] || "Hello!"
# Only try to send this email on a POST
# if request.post?
# or make a feedback form controller and send in the create action
# ActionMailer::Base.mail( FOR TEST PURPOSES
# :from => #email,
# :to => 'erikvdw#comcast.net',
# :subject => "A new contact form message from #{#name}",
# :body => #message).deliver
UserMailer.contact_form(#email, #name, #message).deliver
end
A quick fix would be to just split the string into two parts as such
class UserMailer < ActionMailer::Base
default from: "from#example.com"
def contact_form(email, name, message)
#message = message
mail(:from => email,
:to => 'your-email#example.com',
:subject => "A new contact form message from " + name) <----
end
end
This way the notation is clearer and it will avoid the manual concatenation problem.
After looking up a quick thing, it seems like this might also work. The single quotes are needed internally apparently according to a couple sources I found. I don't use that notation so let me know if it helped!
:subject => "A new contact form message from '#{name}'")
I am having a little trouble with a form in Rails. (I'm new to Rails)
What I get after submitting the form is this:
--- !ruby/hash:ActionController::Parameters
utf8: "✓"
name: Jim
email: Jim#jim.com
subject: hello
message: goodbye
controller: contacts
action: create
It should be like this:
contact:
name: Jim
email: Jim#jim.com
subject: hello
message: goodbye
I have no idea what I'm doing wrong here. Here is the form (minus all the bootstrap divs and spans):
views/contacts/new.html.erb
<%= form_for(#contact, url: contact_path) do |f| %>
<%= f.text_field :name, name: "name", value: nil, class: 'form-control', placeholder: 'Enter full name' %>
<%= f.email_field :email, name: "email", class: 'form-control', placeholder: 'Enter email address' %>
<%= f.text_field :subject, name: "subject", class: 'form-control',
placeholder: 'Enter subject' %>
<%= f.text_area :message, name:"message", class: 'form-control', rows: 6, placeholder: 'Enter your message for us here.' %>
<%= f.submit :submit, class: 'btn btn-default pull-right' %>
<% end %>
config/routes.rb
get 'contact' => 'contacts#new'
post 'contact' => 'contacts#create'
controllers/contacts_controller.rb
class ContactsController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact = Contact.new(params[:contact]) #<-- always fails because no :contact
if #contact.valid?
if #contact.send_mail
# todo
else
# todo
end
else
flash.now[:error] = params.inspect
render 'new'
end
end
end
models/contact.rb
class Contact
include ActiveAttr::Model
attribute :name
attribute :email
attribute :subject
attribute :message
validates_presence_of :name
validates_format_of :email, with: /\A([\w\.%\+\-]+)#([\w\-]+\.)+([\w]{2,})\z/i
validates_presence_of :subject
validates_presence_of :message
def send_mail
ContactMailer.form_message(self).deliver_now
end
end
I have tried using form_for(:contact), routing with resources, changing the model to use the mail_form gem, but still no luck. Of course I could just get all values by doing params[:name] etc. but it bugs me that isn't creating a single hash with all form input values. Does anyone know why this is happening? Thanks in advance.
Remove the name: '...' option, because the helpers already set the name and it's not the one you are setting. In your case, rails will expect that the fields are named like contact[name] and contact[email] instead of the ones you are setting.
I am making a little app based on futureme.org for practice. The user goes to a page, sees a form, fills it out with email, subject, message, and a delivery date. Then the app delivers their message (email) on that date.
The problem I am having, is I am not sure how to set up the delivery date option in the model & in the view (ie. does rails have a date option?). Here is my code;
Letter.rb
class Letter < ActiveRecord::Base
VALID_EMAIL_REGEX = /\A[\w+\-,]+#[a-z\d\-.]+\.[a-z]+\z/i
validates_presence_of :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates_length_of :subject, presence: true, :maximum => 30
validates_presence_of :message
validates_presence_of :deliver_on #not sure if this is right
end
Letters_Controller.rb
class LettersController < ApplicationController
def create
#letter = Letter.new(letter_params)
if #letter.save
LetterMailer.letter_confirm(#letter).deliver
redirect_to letters_path, :notice => "Your letter was sent!"
else
render "welcome/home"
end
end
private
def letter_params
params.require(:letter).permit(:email, :subject, :message)
end
end
lettermailer.rb
class Lettermailer < ActionMailer::Base
default from: "futureself#example.com"
def letter_confirm(letter)
mail(to: #letter.email, subject: "Thanks from Future Self")
end
def letter_email(letter)
#letter = letter
#url = 'http://futureself.herokuapp.com'
mail(to: #letter.email, subject: #letter.subject)
end
end
Home Page Form;
<%= form_for #letter, :html => {:class => 'form-horizontal'} do |f| %>
<% if #letter.errors.any? %>
<div class="error_messages">
<h3><%= pluralize(#letter.errors.count, "error")%> stopped this message from being saved</h3>
<ul>
<% #letter.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :subject %><br />
<%= f.text_field :subject %><br />
</div>
<div class="field">
<%= f.label :message, "Message" %><br />
<%= f.text_area :message, size: "100x10" %>
</div>
<!-- Deliver on Option -->
<div class="field"><%= f.submit "Submit", class: "btn btn-small btn-primary" %></div>
<% end %>
</body>
</html>
Any help at all would be great.
You need a job queue, I would suggest using DelayedJob as it's about as simple as it gets (if you are using ActiveRecord) https://github.com/collectiveidea/delayed_job
Then in your LessonsController
LetterMailer.delay(run_at: #letter.deliver_on).letter_confirm(#letter)
This assumes deliver_on is a DateTime object.
Couple things you might want to consider:
Rails Cast on DelayedJob http://railscasts.com/episodes/171-delayed-job-revised
if someone changes the letter model before it's delivered
TimeZones http://railscasts.com/episodes/106-time-zones-revised
Server implementation of DelayedJob (can be tricky)
Other job queues that are good but rely on redis are http://sidekiq.org/ and https://github.com/resque/resque
Validations
I like to use the validates_timeliness gem. So you can do things like
validates_date :deliver_on, :before => lambda { Time.zone.now + 1.year },
:before_message => "must be earlier one year from today",
:on_or_after => lambda { Time.zone.now.end_of_day },
:on_or_after_message => "must be after today"
Form
You can use jquery-ui-rails
f.input :deliver_on, as: :string, label: "Date of delivery (dd/mm/yyyy)", input_html: {class: "jquery-ui-date", value: f.deliver_on ? l(f.deliver_on) : nil }
Don't get me started on RegEx for email. Try googling it ;)
And yeah like #mattsmith said check out delayed job.
I am not really sure what I am doing wrong.
I see that quite many people have similar problems:
Rails contact form not working,
Rails 3 Contact Form, undefined method?,
Contact Us form in Rails 3 and etc.
Even tough I also see that quite many consider this very simple - to build a contact form.
Been trough popular actionmailer guides: http://guides.rubyonrails.org/action_mailer_basics.html,
http://railscasts.com/episodes/206-action-mailer-in-rails-3
I am not really a developer, so I find this quite confusing.
Anyway, I need to build a simple contact form, to just send the message as an email for a email account of mine. I don't want to store the messages in my db.
Here's my code:
/app/models/message.rb
class Message
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :name, :email, :content
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
end
def persisted?
false
end
end
app\controllers\messages_controller.rb
class MessagesController < ApplicationController
def new
#message = Message.new
end
def create
#message = Message.new(params[:message])
MessageMailer.send(#message).deliver
flash[:notice] = "Message sent! Thank you for contacting us."
redirect_to root_url
end
end
/app/mailer/message_mailer.rb
class MessageMailer < ActionMailer::Base
default :to => "emils.veveris#thrillengine.com"
def send(message)
#message = message
mail( :subject => " Test ", :from => #message.email ) do |format|
format.text
end
end
end
app/views/messages/new.html.erb
<h1> "Contact Us" </h1>
<%= form_for #message do |f| %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :email %><br />
<%= f.text_field :email %>
</p>
<p>
<%= f.label :content, "Message" %><br />
<%= f.text_area :content %>
</p>
<p><%= f.submit "Send Message" %></p>
<% end %>
app/views/message_mailer/sent.text.erb
Message sent by <%= #message.name %>
<%= #message.content %>
and development.rb
N1::Application.configure do
# Don't care if the mailer can't send
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
end
I don't see any errors in log file and I don't receive any error messages.
The mail is just not delivered.
Can You please tell me what I am doing wrong?
Thanks!
This is a little old but maybe some of the concepts can help you...it's pretty much exactly what you're trying to do.
http://railscasts.com/episodes/193-tableless-model