Class: Inquirex::Actions::SendEmail

Inherits:
Base
  • Object
show all
Defined in:
lib/inquirex/actions/send_email.rb

Overview

Declarative email effect. Builds a Mail::Message (the object ActionMailer itself wraps) from {field} templates and appends it to the outbox. Nothing is delivered — the host application sends the messages.

Scalar fields (to, from, cc, bcc, reply_to, subject) and the text body render values verbatim; the html body HTML-escapes every interpolated value automatically. Both bodies given => multipart/alternative.

Bodies accept an inline template String or { file: "path" }, which is read once at definition time and inlined — a definition rehydrated from JSON never touches the filesystem.

Images: reference external URLs in the html body. Attachments are deliberately unsupported.

The mail gem is a soft dependency, required only when a message is actually built. Rails hosts always have it (ActionMailer depends on it).

Constant Summary collapse

SCALAR_FIELDS =

Scalar header fields rendered verbatim via Template.render_text in #to_mail and #to_h.

%i[to from cc bcc reply_to subject].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#serializable?, #validate_against

Constructor Details

#initialize(to:, subject:, from: nil, cc: nil, bcc: nil, reply_to: nil, text: nil, html: nil, headers: {}) ⇒ SendEmail

Returns a new instance of SendEmail.

Parameters:

  • to (String)

    recipient template (required)

  • subject (String)

    subject template (required)

  • text (String, Hash, nil) (defaults to: nil)

    plain-text body template or { file: }

  • html (String, Hash, nil) (defaults to: nil)

    HTML body template or { file: }

  • headers (Hash) (defaults to: {})

    extra headers (values support {field})

Raises:



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/inquirex/actions/send_email.rb', line 44

def initialize(to:, subject:, from: nil, cc: nil, bcc: nil, reply_to: nil,
  text: nil, html: nil, headers: {})
  super()
  @to = to
  @from = from
  @cc = cc
  @bcc = bcc
  @reply_to = reply_to
  @subject = subject
  @text = resolve_body(text)
  @html = resolve_body(html)
  @headers = headers.transform_keys(&:to_s).freeze
  validate!
  freeze
end

Instance Attribute Details

#bccString? (readonly)

Returns optional address templates ({field} placeholders allowed).

Returns:

  • (String, nil)

    optional address templates ({field} placeholders allowed)



30
31
32
# File 'lib/inquirex/actions/send_email.rb', line 30

def bcc
  @bcc
end

#ccString? (readonly)

Returns optional address templates ({field} placeholders allowed).

Returns:

  • (String, nil)

    optional address templates ({field} placeholders allowed)



30
31
32
# File 'lib/inquirex/actions/send_email.rb', line 30

def cc
  @cc
end

#fromString? (readonly)

Returns optional address templates ({field} placeholders allowed).

Returns:

  • (String, nil)

    optional address templates ({field} placeholders allowed)



30
31
32
# File 'lib/inquirex/actions/send_email.rb', line 30

def from
  @from
end

#headersHash{String => String} (readonly)

Returns extra headers (values support {field}).

Returns:

  • (Hash{String => String})

    extra headers (values support {field})



36
37
38
# File 'lib/inquirex/actions/send_email.rb', line 36

def headers
  @headers
end

#htmlString? (readonly)

Returns body template, inlined at definition time when { file: } was given.

Returns:

  • (String, nil)

    body template, inlined at definition time when { file: } was given



33
34
35
# File 'lib/inquirex/actions/send_email.rb', line 33

def html
  @html
end

#reply_toString? (readonly)

Returns optional address templates ({field} placeholders allowed).

Returns:

  • (String, nil)

    optional address templates ({field} placeholders allowed)



30
31
32
# File 'lib/inquirex/actions/send_email.rb', line 30

def reply_to
  @reply_to
end

#subjectString (readonly)

Returns required recipient / subject templates ({field} placeholders allowed).

Returns:

  • (String)

    required recipient / subject templates ({field} placeholders allowed)



27
28
29
# File 'lib/inquirex/actions/send_email.rb', line 27

def subject
  @subject
end

#textString? (readonly)

Returns body template, inlined at definition time when { file: } was given.

Returns:

  • (String, nil)

    body template, inlined at definition time when { file: } was given



33
34
35
# File 'lib/inquirex/actions/send_email.rb', line 33

def text
  @text
end

#toString (readonly)

Returns required recipient / subject templates ({field} placeholders allowed).

Returns:

  • (String)

    required recipient / subject templates ({field} placeholders allowed)



27
28
29
# File 'lib/inquirex/actions/send_email.rb', line 27

def to
  @to
end

Class Method Details

.from_h(hash) ⇒ SendEmail

Parameters:

  • hash (Hash)

    string or symbol keys

Returns:



102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/inquirex/actions/send_email.rb', line 102

def self.from_h(hash)
  fetch = ->(key) { hash[key.to_s] || hash[key.to_sym] }
  new(
    to:       fetch.call(:to),
    from:     fetch.call(:from),
    cc:       fetch.call(:cc),
    bcc:      fetch.call(:bcc),
    reply_to: fetch.call(:reply_to),
    subject:  fetch.call(:subject),
    text:     fetch.call(:text),
    html:     fetch.call(:html),
    headers:  fetch.call(:headers) || {}
  )
end

Instance Method Details

#call(answers, outbox) ⇒ void

This method returns an undefined value.

Builds the message and appends it to the outbox.

Parameters:

  • answers (Answers)

    completed answers

  • outbox (Outbox)

    receives the built Mail::Message



65
66
67
# File 'lib/inquirex/actions/send_email.rb', line 65

def call(answers, outbox)
  outbox.add_message(to_mail(answers))
end

#to_hHash

Returns wire format, same shape .from_h accepts.

Returns:

  • (Hash)

    wire format, same shape .from_h accepts



88
89
90
91
92
93
94
95
96
97
98
# File 'lib/inquirex/actions/send_email.rb', line 88

def to_h
  hash = { "type" => "send_email" }
  SCALAR_FIELDS.each do |field|
    value = public_send(field)
    hash[field.to_s] = value if value
  end
  hash["text"] = @text if @text
  hash["html"] = @html if @html
  hash["headers"] = @headers unless @headers.empty?
  hash
end

#to_mail(answers) ⇒ Mail::Message

Builds a Mail::Message from the templates and the given answers. Pure function — safe to call from a background job to rebuild messages from persisted answers.

Parameters:

Returns:

  • (Mail::Message)


75
76
77
78
79
80
81
82
83
84
85
# File 'lib/inquirex/actions/send_email.rb', line 75

def to_mail(answers)
  require_mail!
  mail = ::Mail.new
  SCALAR_FIELDS.each do |field|
    value = public_send(field)
    mail.public_send(:"#{field}=", Template.render_text(value, answers)) if value
  end
  @headers.each { |name, value| mail.header[name] = Template.render_text(value.to_s, answers) }
  attach_bodies(mail, answers)
  mail
end