Skip to content

Instantly share code, notes, and snippets.

@tmiller
Forked from cypriss/action_mailer_no_tmail.rb
Created June 18, 2013 20:14
Show Gist options
  • Save tmiller/5808900 to your computer and use it in GitHub Desktop.
Save tmiller/5808900 to your computer and use it in GitHub Desktop.
require 'action_mailer'
require 'mail'
module ActionMailer
class TestCase
def set_expected_mail
@expected = Mail.new
@expected.content_type = "text/plain; charset=#{charset}"
@expected.mime_version = '1.0'
end
end
module PartContainer
def field_with_attrs(value, attributes)
[value, *attributes.map { |k,v| "#{k}=#{v}" }].join("; ")
end
end
class Base
adv_attr_accessor :message_id
def clean_address(str)
EmailAddress.parse(str, :no_default_name => true).quoted rescue str
end
def create_mail
m = Mail.new
m.charset = charset
m.subject = subject
m.to = clean_address(recipients)
m.from = clean_address(from)
m.bcc = clean_address(bcc) unless bcc.nil?
m.cc = clean_address(cc) unless cc.nil?
m.reply_to = reply_to unless reply_to.nil?
m.mime_version = mime_version unless mime_version.nil?
m.date = sent_on.to_time rescue sent_on if sent_on
m.message_id = message_id unless message_id.nil?
headers.each { |k, v| m[k] = v }
ctype, ctype_attrs = parse_content_type
if @parts.empty?
if content_type.match(/charset=/i)
m.content_type = field_with_attrs(ctype, ctype_attrs)
else
m.content_type = "#{content_type}; charset=#{charset}"
end
m.body = normalize_new_lines(body)
else
if String === body
part = Mail::Part.new
part.body = normalize_new_lines(body)
part.content_type = field_with_attrs(ctype, ctype_attrs)
part.content_disposition = "inline"
m.add_part part
end
@parts.each do |p|
part = (Mail::Part === p ? p : p.to_mail(self))
m.add_part(part)
end
if ctype =~ /multipart/
ctype_attrs.delete "charset"
m.content_type = field_with_attrs(ctype, ctype_attrs)
end
end
@mail = m
end
def perform_delivery_smtp(mail)
destinations = mail.destinations
mail.ready_to_send!
sender = (mail['return-path'] && mail['return-path'].address) || Array(mail.from).first
smtp = Net::SMTP.new(smtp_settings[:address], smtp_settings[:port])
smtp.enable_starttls_auto if smtp_settings[:enable_starttls_auto] && smtp.respond_to?(:enable_starttls_auto)
smtp.start(smtp_settings[:domain], smtp_settings[:user_name], smtp_settings[:password],
smtp_settings[:authentication]) do |smtp|
smtp.sendmail(mail.encoded, sender, destinations)
end
end
end
class Part
def to_mail(defaults)
part = Mail.new
ctype, ctype_attrs = parse_content_type(defaults)
if @parts.empty?
part.content_transfer_encoding = transfer_encoding || "quoted-printable"
case (transfer_encoding || "").downcase
when "base64" then
part.body = Mail::Encodings::Base64.encode(body)
when "quoted-printable"
part.body = [normalize_new_lines(body)].pack("M*")
else
part.body = body
end
# Always set the content_type after setting the body and or parts!
# Also don't set filename and name when there is none (like in
# non-attachment parts)
if content_disposition == "attachment"
ctype_attrs.delete "charset"
part.content_type = field_with_attrs(ctype,
squish("name" => filename).merge(ctype_attrs))
part.content_disposition = field_with_attrs(content_disposition,
squish("filename" => filename).merge(ctype_attrs))
else
part.content_type field_with_attrs(ctype, ctype_attrs)
part.content_disposition = content_disposition
end
else
if String === body
@parts.unshift Part.new(
:charset => charset,
:body => @body,
:content_type => 'text/plain'
)
@body = nil
end
@parts.each do |p|
prt = (Mail::Part === p ? p : p.to_mail(defaults))
part.add_part(prt)
end
if ctype =~ /multipart/
ctype_attrs.delete 'charset'
part.content_type = field_with_attrs(ctype, ctype_attrs)
end
end
headers.each { |k,v| part[k] = v }
part
end
end
end
@PratheepV
Copy link

Hi,

I was just trying the mail in rails 2.3.18 with you patch, the problem is whenever I send a mail its not showing any data in my gmail, instead having _noname_ attachment with _This is a multi-part message in MIME format..._. I tried setting the boundary also even then it not working.

I am using the bellow patch for setting boundary

class ApplicationMailer < ActionMailer::Base
  def create_mail
    m = super

    # fix missing boundary for multipart in old mailer api <-> https://github.com/rails/rails/pull/3090
    if m.content_type =~ /^multipart/ && !m.content_type.include?("boundary=") && m.body.boundary.present?
        ctype_attrs["boundary"] = m.body.boundary
        m.content_type = field_with_attrs(ctype, ctype_attrs)
    end

    m
  end
end

rails/rails#3090 (comment)

please help me with some inputs.

Thanks,
Pratheepv

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment