Created
September 11, 2024 13:46
-
-
Save andynu/cd468b2799701c16bae322b82c10495a to your computer and use it in GitHub Desktop.
Email merge script in ruby
This file contains 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 ruby | |
# Encoding: utf-8 | |
# | |
# This takes a csv file of values, and a txt file as a template | |
# and sends out a pile of customized emails. | |
# | |
require 'csv' | |
require 'mail' | |
class EmailMerge | |
def initialize(data_file, template_file) | |
@data = parse_data(data_file) | |
@subject, @body = parse_template(template_file) | |
@from = "[email protected]" | |
@to_field = "email" | |
end | |
def from=(email) | |
@from = email | |
end | |
def to_field=(field_name) | |
@to_field = field_name | |
end | |
def to(data) | |
data[@to_field] | |
end | |
def recipients | |
@data.map{|data| data[@to_field] } | |
end | |
def preview(n=1) | |
@data[0..n-1].each do |data| | |
puts "-"*80 | |
puts "Subject: "+ render(@subject, data) | |
puts "-"*80 | |
puts render(@body, data) | |
puts "-"*80 | |
end | |
end | |
def render(template, data) | |
text = template.dup | |
text.gsub(/{{(.+?)}}/) do |match| | |
var = match.gsub(/{{/,'').gsub(/}}/,'') | |
data[var] | |
end | |
end | |
def deliver_all!(opts={}) | |
@data.each do |data| | |
mail(data, opts) | |
end | |
end | |
def deliver_n!(n=1, opts={}) | |
@data[0..n-1].each do |data| | |
mail(data, opts) | |
end | |
end | |
# you can override :from, :to, :subject, :body, with opts | |
def mail(data, opts={}) | |
mail = Mail.new | |
mail.delivery_method :sendmail | |
mail.charset = 'UTF-8' | |
mail.content_transfer_encoding = "8bit" | |
mail.content_type = 'text/html' | |
mail.from = opts[:from] || @from | |
mail.to = opts[:to] || data[@to_field] | |
mail.subject = opts[:subject] || self.render(@subject, data) | |
mail.body = opts[:body] || self.render(@body, data) | |
ok = mail.deliver! | |
p [ok, mail] | |
end | |
private | |
def parse_template(template_file) | |
text = File.readlines(template_file) | |
[ | |
text.shift.gsub(/Subject:\s+/i,'').strip, | |
text.join.strip | |
] | |
end | |
# reads file, returns array of hashes based on the header | |
def parse_data(data_file) | |
data = [] | |
headers = nil | |
CSV.open(data_file).each do |row| | |
if headers.nil? | |
headers = row | |
else | |
data << Hash[*headers.zip(row).flatten] | |
end | |
end | |
data | |
end | |
end | |
if $0 == __FILE__ | |
base_dir = "data/campaign_20140314" | |
data_file = "#{base_dir}/data.csv" | |
template_file = "#{base_dir}/template.html" | |
em = EmailMerge.new(data_file, template_file) | |
em.from = "[email protected]" | |
em.to_field = "email" | |
testing = true | |
if testing | |
em.preview 1 # show a few | |
puts em.recipients # show were they'd go if we ran it for real | |
em.deliver_n!(n=1, to: '[email protected]') # test deliver a few | |
end | |
# DO IT FOR REAL, CAREFUL! TEST FIRST | |
#em.deliver_all!(to: '[email protected]') | |
#em.deliver_all! | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment