Created
December 11, 2014 06:30
-
-
Save nelsnelson/bbe061dd34896fe5cc60 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env jruby | |
require 'mail' | |
require 'optparse' | |
require 'pony' | |
require 'securerandom' | |
require 'zlib' | |
module Mail | |
class AttachmentsList < Array | |
def []=(name, value) | |
encoded_name = Mail::Encodings.decode_encode name, :encode | |
default_values = { :content_type => "#{set_mime_type(name)}; name=\"#{encoded_name}\"", | |
:content_transfer_encoding => "#{guess_encoding}", | |
:content_disposition => "#{@content_disposition_type}; filename=\"#{encoded_name}\"" } | |
if value.is_a?(Hash) | |
default_values[:body] = value.delete(:content) if value[:content] | |
default_values[:body] = value.delete(:data) if value[:data] | |
encoding = value.delete(:transfer_encoding) || value.delete(:encoding) | |
if encoding | |
if Mail::Encodings.defined? encoding | |
default_values[:content_transfer_encoding] = encoding | |
else | |
raise "Do not know how to handle Content Transfer Encoding #{encoding}, please choose either quoted-printable or base64" | |
end | |
end | |
if value[:mime_type] | |
default_values[:content_type] = value.delete(:mime_type) | |
@mime_type = MIME::Types[default_values[:content_type]].first | |
default_values[:content_transfer_encoding] ||= guess_encoding | |
end | |
hash = default_values.merge(value) | |
else | |
default_values[:body] = value | |
hash = default_values | |
end | |
if hash[:body].respond_to? :force_encoding and hash[:body].respond_to? :valid_encoding? | |
if not hash[:body].valid_encoding? and default_values[:content_transfer_encoding].downcase == "binary" | |
hash[:body].force_encoding("BINARY") | |
end | |
end | |
attachment = Part.new(hash) | |
attachment.add_content_id(hash[:content_id]) | |
@parts_list << attachment | |
end | |
end | |
class ParameterHash < IndifferentHash | |
def encoded | |
map.sort_by { |a| a.first.to_s }.map! do |key_name, value| | |
unless value.ascii_only? | |
value = Mail::Encodings.param_encode(value) | |
key_name = "#{key_name}*" | |
end | |
if key_name =~ /name/ | |
%Q{#{key_name}="#{quote_token(value)}"} | |
else | |
%Q{#{key_name}=#{quote_token(value)}} | |
end | |
end.join(";\s") | |
end | |
end | |
class ContentDispositionField < StructuredField | |
def encoded | |
if parameters.length > 0 | |
p = ";\s#{parameters.encoded}\r\n" | |
else | |
p = "\r\n" | |
end | |
"#{CAPITALIZED_FIELD}: #{disposition_type}" + p | |
end | |
end | |
class ContentTypeField < StructuredField | |
def string | |
sub_type.gsub! /^gzip$/, 'x-gzip' | |
"#{main_type}/#{sub_type}" | |
end | |
def encoded | |
parameters.delete 'charset' if parameters.keys.include? 'name' or parameters.keys.include? 'filename' | |
if parameters.length > 0 | |
p = ";\s#{parameters.encoded}" | |
else | |
p = "" | |
end | |
"#{CAPITALIZED_FIELD}: #{content_type}#{p}\r\n" | |
end | |
end | |
class ContentIdField < StructuredField | |
def encoded | |
"#{CAPITALIZED_FIELD}: #{to_s}\r\nX-Attachment-Id: f_#{SecureRandom.hex[0..8]}\r\n" | |
end | |
end | |
end | |
def gzip(file) | |
gzip = "#{file}.gz" | |
Zlib::GzipWriter.open(gzip) do |gz| | |
File.open(file, 'rb') do |io| | |
while chunk = io.read(16 * 1024) do | |
gz.write chunk | |
end | |
end | |
gz.close | |
end | |
gzip | |
end | |
def send_email(to, from, subject, message='', attachment=nil, compress=false) | |
begin | |
options = { | |
:via => :smtp, | |
:via_options => { | |
:address => 'smtp.gmail.com', | |
:port => '587', | |
:enable_starttls_auto => true, | |
:user_name => '[email protected]', | |
:password => 'password', | |
:authentication => :plain, | |
:domain => 'host.com' | |
}, | |
:to => to, | |
:from => from, | |
:subject => subject, | |
:html_body => message, | |
:body => message | |
} | |
if attachment | |
attachment = File.expand_path attachment | |
attachment = gzip attachment if compress | |
content = open(attachment, 'rb') { |io| io.read } | |
basename = File.basename attachment | |
attachment_options = { | |
:attachments => { | |
basename => content | |
}, | |
:headers => { | |
'Content-Type' => 'multipart/mixed', | |
'Content-Transfer-Encoding' => 'base64', | |
'Content-Disposition' => 'attachment' | |
} | |
} | |
options.merge! attachment_options | |
end | |
mail = Pony.mail options | |
File.delete attachment if compress | |
rescue Exception => ex | |
puts "Error posting email: #{ex.message}" | |
puts ex.backtrace | |
return ex.message | |
end | |
nil | |
end | |
@options = Hash.new | |
OptionParser.new do |opt| | |
opt.banner = "Usage: #{File.basename $0} [options]" | |
opt.on('--to=to', 'To: recipient e-mail address') { |v| @options[:to_address] = v } | |
opt.on('--from=from', 'From: sender e-mail address') { |v| @options[:from_address] = v } | |
opt.on('--subject=subject', 'Subject: e-mail subject') { |v| @options[:subject] = v } | |
opt.on('--message=message', 'Message: e-mail message body') { |v| @options[:message] = v } | |
opt.on('--attachment=attachment', 'Attachment: file to attach') { |v| @options[:attachment] = v } | |
opt.on('--compress', 'Compress attachment') { |v| @options[:compress] = v } | |
opt.on_tail("-?", "--help", "Show this message") do | |
puts opt | |
exit | |
end | |
opt.on_tail("--version", "Show version") do | |
puts "#{File.basename($0)} version 1.0" | |
exit | |
end | |
begin | |
opt.parse!(ARGV) | |
rescue OptionParser::InvalidOption => e | |
puts opt | |
exit | |
end | |
@options[:compress] ||= false | |
end | |
def main | |
send_email( | |
@options[:to_address], | |
@options[:from_address], | |
@options[:subject], | |
@options[:message], | |
@options[:attachment], | |
@options[:compress] | |
) | |
end | |
main if __FILE__ == $0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment