Class: LetterOpener::Message

Inherits:
Object
  • Object
show all
Defined in:
lib/letter_opener/message.rb

Constant Summary collapse

ERROR_MSG =
'%s or default configuration must be given'.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(mail, options = {}) ⇒ Message

Returns a new instance of Message.

Raises:

  • (ArgumentError)


21
22
23
24
25
26
27
28
29
30
# File 'lib/letter_opener/message.rb', line 21

def initialize(mail, options = {})
  @mail = mail
  @location = options[:location] || LetterOpener.configuration.location
  @part = options[:part]
  @template = options[:message_template] || LetterOpener.configuration.message_template
  @attachments = []

  raise ArgumentError, ERROR_MSG % 'options[:location]' unless @location
  raise ArgumentError, ERROR_MSG % 'options[:message_template]' unless @template
end

Instance Attribute Details

#mailObject (readonly)

Returns the value of attribute mail.



8
9
10
# File 'lib/letter_opener/message.rb', line 8

def mail
  @mail
end

Class Method Details

.rendered_messages(mail, options = {}) ⇒ Object



10
11
12
13
14
15
16
17
# File 'lib/letter_opener/message.rb', line 10

def self.rendered_messages(mail, options = {})
  messages = []
  messages << new(mail, options.merge(part: mail.html_part)) if mail.html_part
  messages << new(mail, options.merge(part: mail.text_part)) if mail.text_part
  messages << new(mail, options) if messages.empty?
  messages.each(&:render)
  messages.sort
end

Instance Method Details

#<=>(other) ⇒ Object



134
135
136
137
# File 'lib/letter_opener/message.rb', line 134

def <=>(other)
  order = %w[rich plain]
  order.index(type) <=> order.index(other.type)
end

#attachment_filename(attachment) ⇒ Object



127
128
129
130
131
132
# File 'lib/letter_opener/message.rb', line 127

def attachment_filename(attachment)
  # Copied from https://github.com/rails/rails/blob/6bfc637659248df5d6719a86d2981b52662d9b50/activestorage/app/models/active_storage/filename.rb#L57
  attachment.filename.encode(
    Encoding::UTF_8, invalid: :replace, undef: :replace, replace: "").strip.tr("\u{202E}%$|:;/\t\r\n\\", "-"
  )
end


117
118
119
120
121
# File 'lib/letter_opener/message.rb', line 117

def auto_link(text)
  text.gsub(URI::Parser.new.make_regexp(%W[https http])) do |link|
    "<a href=\"#{ link }\">#{ link }</a>"
  end
end

#bccObject



101
102
103
# File 'lib/letter_opener/message.rb', line 101

def bcc
  @bcc ||= Array(@mail['bcc']).join(", ")
end

#bodyObject



69
70
71
72
73
74
75
76
77
78
79
# File 'lib/letter_opener/message.rb', line 69

def body
  @body ||= begin
    body = (@part || @mail).decoded

    mail.attachments.each do |attachment|
      body.gsub!(attachment.url, "attachments/#{attachment_filename(attachment)}")
    end

    body
  end
end

#ccObject



97
98
99
# File 'lib/letter_opener/message.rb', line 97

def cc
  @cc ||= Array(@mail['cc']).join(", ")
end

#content_typeObject



65
66
67
# File 'lib/letter_opener/message.rb', line 65

def content_type
  @part && @part.content_type || @mail.content_type
end

#encodingObject



113
114
115
# File 'lib/letter_opener/message.rb', line 113

def encoding
  body.respond_to?(:encoding) ? body.encoding : "utf-8"
end

#filepathObject



61
62
63
# File 'lib/letter_opener/message.rb', line 61

def filepath
  File.join(@location, "#{type}.html")
end

#fromObject



81
82
83
# File 'lib/letter_opener/message.rb', line 81

def from
  @from ||= Array(@mail['from']).join(", ")
end

#h(content) ⇒ Object



123
124
125
# File 'lib/letter_opener/message.rb', line 123

def h(content)
  CGI.escapeHTML(content)
end

#renderObject



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/letter_opener/message.rb', line 32

def render
  FileUtils.mkdir_p(@location)

  if mail.attachments.any?
    attachments_dir = File.join(@location, 'attachments')
    FileUtils.mkdir_p(attachments_dir)
    mail.attachments.each do |attachment|
      filename = attachment_filename(attachment)
      path = File.join(attachments_dir, filename)

      unless File.exist?(path) # true if other parts have already been rendered
        File.open(path, 'wb') { |f| f.write(attachment.body.raw_source) }
      end

      @attachments << [attachment.filename, "attachments/#{filename}"]
    end
  end

  File.open(filepath, 'w') do |f|
    f.write ERB.new(template).result(binding)
  end

  mail["location_#{type}"] = filepath
end

#reply_toObject



105
106
107
# File 'lib/letter_opener/message.rb', line 105

def reply_to
  @reply_to ||= Array(@mail['reply-to']).join(", ")
end

#senderObject



85
86
87
# File 'lib/letter_opener/message.rb', line 85

def sender
  @sender ||= Array(@mail['sender']).join(", ")
end

#subjectObject



89
90
91
# File 'lib/letter_opener/message.rb', line 89

def subject
  @subject ||= @mail.subject
end

#templateObject



57
58
59
# File 'lib/letter_opener/message.rb', line 57

def template
  File.read(File.expand_path("../templates/#{@template}.html.erb", __FILE__))
end

#toObject



93
94
95
# File 'lib/letter_opener/message.rb', line 93

def to
  @to ||= Array(@mail['to']).join(", ")
end

#typeObject



109
110
111
# File 'lib/letter_opener/message.rb', line 109

def type
  content_type =~ /html/ ? "rich" : "plain"
end