I've made a simple form for sending emails with attachments. The problem is that I don't know how to make it work in the mailer. All tutorials that I've found so far are covering the scenario when the file for the attachment is already somewhere one the server and I wasn't able to find anything about validating email contents.
So, I've got 2 questions for you:
- How can I let users send emails with attachments uploaded by them?
- How can I validate user's inputs and extensions of attachments?
My email form...
<div id="form_wrapper">
<%= form_for开发者_如何学运维(:kontakt, :url => {:action => 'kontakt'}, :html => { :multipart => true }, :remote=>true) do |f| %>
<ul>
<li>
<%= f.label(:email) %>
<%= f.text_field(:email) %>
</li>
<li>
<%= f.label(:content) %>
<%= f.text_area(:content, :size => "42x7") %>
</li>
<li>
<%= f.label(:preview, :class=>:preview )%>
<%= f.file_field :preview %>
</li>
</ul>
<%= image_submit_tag("blank.gif",:id=>"send_email", :class=>"action submit") %>
<%= link_to("Reset", {:controller=>'frontend',:action => 'index'},:remote => true, :class => 'action reset') %>
<% end %>
</div>
<%= javascript_include_tag 'jquery.form.js','jquery.rails','jquery.remotipart' %>
and my mailer...
class Contact < ActionMailer::Base
default :from => "xxxxx@gmail.com"
def wiadomosc(email)
@content=email[:content]
file=email[:preview]
attachments[file.original_filename] =File.read(file.path)
mail(
:subject=>"www.XXXXXX.pl - you've got a new message",
:reply_to =>"xxxxx@gmail.com",
:to => email[:email]
)
end
end
I came up with attachments[file.original_filename] =File.read(file.path)
and it's adding attachments but the files are coruppted and cannot be opened...
Any thoughts or links would be greatly appreciated.
I've found that if you want to send email with attachment in rails, you need to attach it that way...
attachments[file.original_filename] = File.open(file.path, 'rb'){|f| f.read}
So the whole mailer method might look like this...
def message(email)
@content=email[:content]
unless email[:email_attachment].nil?
file=email[:email_attachment]
attachments[file.original_filename] = File.open(file.path, 'rb'){|f| f.read}
end
mail(
:subject=>"www.XXXXXX.pl - you've got a new message",
:reply_to =>"xxxxx@gmail.com",
:to => email[:email]
)
end
As for the validations, there are two methods that I've found. First one is quite obvious. You have to create a table in your database and validate form's inputs in model just like you always do. If you do it that way than everything will be saved in your database. It has some advantages, for exmple: you can use it as an archive or for some kind of statistics about your clients in your app or even put it through some sql triggers. However, if you don't want to save anything than you can create "tableless model" (Railscasts #193 and original Codetunes). All you have to do is to place this code at the begining of your model:
def self.columns() @columns ||= []; end
def self.column(name, sql_type = nil, default = nil, null = true)
columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
end
Than you have to list your columns...
column :name, :string
column :company, :string
column :email, :string
column :content, :text
column :type_of_question, :string
column :email_attachment, :string
And after that you can place your model's code...
has_attached_file :email_attachment
EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
TYPES = ['application/zip', 'multipart/x-zip', 'application/x-zip-compressed']
validates :name, :presence => {:message => "Blah blah blah"}
validates :email, :presence => {:message => "Blah blah blah"},
:format=>{:unless=> Proc.new{|s| s.email.nil?|| s.email.empty? },
:with => EMAIL_REGEX, :message => "Blah blah blah"}
validates :content, :presence => {:message => "Blah blah blah"}
validates_inclusion_of :type_of_question, :in => ["Blah1", "Blah2", "Blah3"],
:message => "%{value} is not on the list of types"
validates_attachment_content_type :email_attachment, :content_type => TYPES,
:message => "The attachment has wrong extension..."
Right now, I'm using Gmail for sending emails but it's quite slooow. It takes about 2 minutes to send a short message with 2Kb test attachment. Have you got any suggestions about how to speed up this process? Maybe you can recomend another provider or solution?
PS. Don't forget to check out 'client side validations' Railscasts #263
精彩评论