Permalink
Browse files

Update addresses passed into sendmail to escape them (Andy Lindeman)

  • Loading branch information...
mikel committed Jan 26, 2011
1 parent 95ebfb7 commit 12bfaad0d240bfd3912cfb640bedcb38db4c6f33
Showing with 72 additions and 15 deletions.
  1. +2 −0 lib/mail.rb
  2. +55 −0 lib/mail/core_extensions/shellwords.rb
  3. +15 −15 lib/mail/network/delivery_methods/sendmail.rb
View
@@ -2,6 +2,7 @@
module Mail # :doc:
require 'date'
require 'shellwords'
require 'active_support'
require 'active_support/core_ext/class/attribute_accessors'
@@ -33,6 +34,7 @@ module Mail # :doc:
require 'mail/core_extensions/nil'
require 'mail/core_extensions/string'
require 'mail/core_extensions/shellwords' unless String.new.respond_to?(:shellescape)
require 'mail/core_extensions/smtp' if RUBY_VERSION < '1.9.3'
require 'mail/patterns'
@@ -0,0 +1,55 @@
# The following is imported from ruby 1.9.2 shellwords.rb
#
module Shellwords
# Escapes a string so that it can be safely used in a Bourne shell
# command line.
#
# Note that a resulted string should be used unquoted and is not
# intended for use in double quotes nor in single quotes.
#
# open("| grep #{Shellwords.escape(pattern)} file") { |pipe|
# # ...
# }
#
# +String#shellescape+ is a shorthand for this function.
#
# open("| grep #{pattern.shellescape} file") { |pipe|
# # ...
# }
#
def shellescape(str)
# An empty argument will be skipped, so return empty quotes.
return "''" if str.empty?
str = str.dup
# Process as a single byte sequence because not all shell
# implementations are multibyte aware.
str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/n, "\\\\\\1")
# A LF cannot be escaped with a backslash because a backslash + LF
# combo is regarded as line continuation and simply ignored.
str.gsub!(/\n/, "'\n'")
return str
end
module_function :shellescape
class << self
alias escape shellescape
end
end
class String
# call-seq:
# str.shellescape => string
#
# Escapes +str+ so that it can be safely used in a Bourne shell
# command line. See +Shellwords::shellescape+ for details.
#
def shellescape
Shellwords.escape(self)
end
end
@@ -1,57 +1,57 @@
module Mail
# A delivery method implementation which sends via sendmail.
#
#
# To use this, first find out where the sendmail binary is on your computer,
# if you are on a mac or unix box, it is usually in /usr/sbin/sendmail, this will
# be your sendmail location.
#
#
# Mail.defaults do
# delivery_method :sendmail
# end
#
#
# Or if your sendmail binary is not at '/usr/sbin/sendmail'
#
#
# Mail.defaults do
# delivery_method :sendmail, :location => '/absolute/path/to/your/sendmail'
# end
#
#
# Then just deliver the email as normal:
#
#
# Mail.deliver do
# to 'mikel@test.lindsaar.net'
# from 'ada@test.lindsaar.net'
# subject 'testing sendmail'
# body 'testing sendmail'
# end
#
#
# Or by calling deliver on a Mail message
#
#
# mail = Mail.new do
# to 'mikel@test.lindsaar.net'
# from 'ada@test.lindsaar.net'
# subject 'testing sendmail'
# body 'testing sendmail'
# end
#
#
# mail.deliver!
class Sendmail
def initialize(values)
self.settings = { :location => '/usr/sbin/sendmail',
:arguments => '-i -t' }.merge(values)
end
attr_accessor :settings
def deliver!(mail)
envelope_from = mail.return_path || mail.sender || mail.from_addrs.first
return_path = "-f \"#{envelope_from}\"" if envelope_from
return_path = "-f \"#{envelope_from.to_s.shellescape}\"" if envelope_from
arguments = [settings[:arguments], return_path].compact.join(" ")
Sendmail.call(settings[:location], arguments, mail.destinations.join(" "), mail)
Sendmail.call(settings[:location], arguments, mail.destinations.collect(&:shellescape).join(" "), mail)
end
def Sendmail.call(path, arguments, destinations, mail)
IO.popen("#{path} #{arguments} #{destinations}", "w+") do |io|
io.puts mail.encoded.to_lf

0 comments on commit 12bfaad

Please sign in to comment.