Class: Jekyll::Newsletter

Inherits:
Object
  • Object
show all
Defined in:
lib/jekyll/newsletter.rb

Constant Summary collapse

CONFIG =
{
  delivery_method: :logger,
  options: {
    user_name: ENV['JEKYLL_NEWSLETTER_USERNAME'],
    password: ENV['JEKYLL_NEWSLETTER_PASSWORD']
  }
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(site) ⇒ Newsletter

Returns a new instance of Newsletter.



17
18
19
# File 'lib/jekyll/newsletter.rb', line 17

def initialize(site)
  @site = site
end

Instance Attribute Details

#siteObject (readonly)

Returns the value of attribute site.



7
8
9
# File 'lib/jekyll/newsletter.rb', line 7

def site
  @site
end

Instance Method Details

#configObject

TODO: Refactor this mess



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/jekyll/newsletter.rb', line 66

def config
  @config ||= Jekyll::Utils.deep_merge_hashes(CONFIG,
                                              (site.config['newsletter'] || {}).transform_keys(&:to_sym)).tap do |config|

    config[:from] ||= ENV['JEKYLL_NEWSLETTER_FROM']
    config[:to] = [config[:to]].flatten
    config[:to].concat(ENV['JEKYLL_NEWSLETTER_TO']&.split(',')&.map(&:strip) || [])
    config[:to].compact!

    %i[to from].each do |o|
      raise Jekyll::Errors::InvalidConfigurationError, "Missing `newsletter.#{o}` in _config.yml" if config[o].nil? || config[o].empty?
    end

    config[:delivery_method] = config[:delivery_method].to_sym
    config[:options].transform_keys!(&:to_sym)
    config[:options][:user_name] ||= config[:from].scan(/<([^>]+)>/)&.flatten&.first || config[:from]
    config[:options][:domain] ||= config[:from].split('@').last
    config[:options][:address] ||= "smtp.#{config[:options][:domain]}"
    config[:delivery_method] = :logger unless production?
  end.freeze
end

#deliverObject



21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/jekyll/newsletter.rb', line 21

def deliver
  return false unless post

  Jekyll.logger.info "Sending #{post.data['title']} as newsletter"

  return false unless mail.deliver

  Jekyll.logger.info 'Newsletter sent'

  cache[key_for_post(post)] = Time.now if production?

  true
end

#mailObject



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/jekyll/newsletter.rb', line 47

def mail
  @mail ||= begin
    mail = Mail.new
    mail.from      = config[:from]
    mail.to        = config[:to]
    mail.subject   = post.data['title']
    mail.html_part = post.content
    # TODO: We don't have access to Markdown on post_write because
    # Jekyll replaces the contents with the rendered output, but we
    # could keep *some* formatting.
    mail.text_part = post.content.gsub(/<[^>]+>/m, '')

    mail.delivery_method config[:delivery_method], **config[:options]

    mail
  end
end

#postObject

Select the newest Post that hasn’t been sent already. Jekyll::Collection doesn’t guarantee order so we convert to a Liquid drop to get the ordered Posts.



38
39
40
41
42
43
44
45
# File 'lib/jekyll/newsletter.rb', line 38

def post
  @post ||= site.to_liquid['site']['posts'].find do |post|
    !cache[key_for_post(post)]
  rescue StandardError
    # When the post isn't in the cache
    true
  end
end