#!/usr/bin/env ruby # Copyright (c) 2018-2019 Yegor Bugayenko # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the 'Software'), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. STDOUT.sync = true require 'slop' require 'mail' require 'net/smtp/proxy' require_relative '../lib/rumble' require_relative '../lib/rumble/version' begin args = [] config = File.expand_path('~/.rumble') if File.exist?(config) body = File.read(config) extra = body.split(/[\r\n]+/).map(&:strip) args += extra puts "Found #{body.split(/\n/).length} lines in #{config}" else puts "Default config file #{config} not found" end args += ARGV begin opts = Slop.parse(args, strict: true, help: true) do |o| o.banner = "Usage (#{Rumble::VERSION}): rumble [options]" o.bool '--help', 'Show these instructions' do puts o exit end o.bool '-v', '--version', 'Show current version' do puts Rumble::VERSION exit end o.bool '--dry', 'Dry run, no emails will be delivered' o.string '--from', 'Full SMTP From field, e.g. "John Doe "', required: true o.string '--method', 'How to deliver them: "smtp" or "sendmail" (default: sendmail)', default: 'sendmail' o.string '--host', 'SMTP host name' o.string '--port', 'SMTP port number (25 by default)', default: 25 o.string '--user', 'SMTP user name' o.string '--password', 'SMTP password' o.string '--proxy', 'HTTP proxy, e.g. "192.168.0.1:8080"' o.string '--subject', 'Email subject', required: true o.string '--letter', 'File name with Liquid template', required: true o.string '--csv', 'CSV file with first name, last name, and email cols' o.string '--resume', 'Email address from which we should resume' o.string '--skip', 'File name with emails that opted-out (black list)' o.string '--test', 'Email address to use instead of the real user list' o.string '--col-first', 'First name columm (0 by default)', default: 0 o.string '--col-last', 'Last name columm (1 by default)', default: 1 o.string '--col-email', 'Email columm (2 by default)', default: 2 end rescue Slop::Error => ex raise "#{ex.message}, try --help" end Encoding.default_external = Encoding::UTF_8 Encoding.default_internal = Encoding::UTF_8 puts 'It is "dry" run, no emails will be actually sent!' if opts[:dry] Mail.defaults do case opts[:method].downcase.strip when 'sendmail' puts "--host=#{opts[:host]} is not allowed w/sendmail" if opts[:host] puts "--port=#{opts[:port]} is not allowed w/sendmail" if opts[:port] puts "--user=#{opts[:user]} is not allowed w/sendmail" if opts[:user] puts '--password is not allowed when using sendmail' if opts[:password] delivery_method :sendmail when 'smtp' raise '--host is required' unless opts[:host] raise '--port is required' unless opts[:port] raise '--user is required' unless opts[:user] raise '--password is required' unless opts[:password] if opts[:proxy] host, port = opts[:proxy].strip.split(':') delivery_method Net::SMTP::Proxy::DeliveryMethod, { address: opts[:host], port: opts[:port], proxy_address: "http://#{host.strip}", proxy_port: port, openssl_verify_mode: OpenSSL::SSL::VERIFY_NONE, domain: 'gmail.com' } else delivery_method :smtp, { :address => opts[:host], :port => opts[:port], :user_name => opts[:user], :password => opts[:password], :enable_starttls_auto => true } end else raise "Delivery method #{opts[:method]} is not supported" end end Rumble::CLI.new(opts).send rescue StandardError => ex puts "#{Rainbow('ERROR').red} (#{ex.class.name}): #{ex.message}" puts ex.backtrace exit(255) end