Module: Goodmail

Extended by:
Configuration
Defined in:
lib/goodmail.rb,
lib/goodmail/email.rb,
lib/goodmail/error.rb,
lib/goodmail/layout.rb,
lib/goodmail/mailer.rb,
lib/goodmail/builder.rb,
lib/goodmail/version.rb,
lib/goodmail/dispatcher.rb,
lib/goodmail/configuration.rb

Overview

The main namespace for the Goodmail gem. Provides configuration and the primary .compose method.

Defined Under Namespace

Modules: Configuration, Dispatcher, Layout Classes: Builder, EmailParts, Error, Mailer

Constant Summary collapse

VERSION =
"0.3.0"

Constants included from Configuration

Configuration::DEFAULT_CONFIG, Configuration::REQUIRED_CONFIG_KEYS

Class Method Summary collapse

Methods included from Configuration

config, configure, reset_config!

Class Method Details

.compose(headers = {}, &block) ⇒ Mail::Message

Composes a Mail::Message object using the Goodmail DSL and layout.

This is the primary entry point for creating emails with Goodmail. The returned Mail::Message object can then have ‘.deliver_now` or `.deliver_later` called on it.

Examples:

mail = Goodmail.compose(to: '[email protected]', subject: 'Hello!') do
  text "This is the email body."
  button "Click Me", "https://example.com"
end

mail.deliver_now
# or
mail.deliver_later


44
45
46
47
# File 'lib/goodmail.rb', line 44

def self.compose(headers = {}, &block)
  # Delegate the actual building process to the Dispatcher
  Dispatcher.build_message(headers, &block)
end

.render(headers = {}, &dsl_block) ⇒ Goodmail::EmailParts

Renders the email content using the Goodmail DSL and returns HTML and text parts. This method does not send the email but prepares its content for sending.



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/goodmail/email.rb', line 16

def self.render(headers = {}, &dsl_block)
  # 1. Initialize the Builder and execute the DSL block
  builder = Goodmail::Builder.new
  builder.instance_eval(&dsl_block) if block_given?
  core_html_content = builder.html_output

  # 2. Determine unsubscribe_url and preheader
  #    These are removed from headers as they are Goodmail-specific, not standard mail headers.
  current_headers = headers.dup # Avoid modifying the original headers hash directly
  unsubscribe_url = current_headers.delete(:unsubscribe_url) || Goodmail.config.unsubscribe_url
  preheader = current_headers.delete(:preheader) || Goodmail.config.default_preheader || current_headers[:subject]

  # 3. Render the raw HTML body using the Layout
  #    The subject is passed for the <title> tag and potentially other uses in layout.
  #    Unsubscribe URL and preheader are passed for inclusion in the layout.
  raw_html_body = Goodmail::Layout.render(
    core_html_content,
    current_headers[:subject], # Use subject from (potentially modified) current_headers
    unsubscribe_url: unsubscribe_url,
    preheader: preheader
  )

  # 4. Use Premailer to inline CSS and generate plaintext
  premailer = Premailer.new(
    raw_html_body,
    with_html_string: true,
    adapter: :nokogiri,
    preserve_styles: false, # Force inlining and remove <style> block
    remove_ids: true,       # Remove IDs
    remove_comments: false  # Keep MSO conditional comments
  )

  final_inlined_html = premailer.to_inline_css
  generated_plain_text = premailer.to_plain_text

  # 5. Perform refined plaintext cleanup (ported from Goodmail::Mailer)
  # 5.1. Remove logo alt text line (if logo exists and has associated URL)
  if Goodmail.config.logo_url.present? && Goodmail.config.company_url.present? && Goodmail.config.company_name.present?
    company_name_escaped = Regexp.escape(Goodmail.config.company_name)
    company_url_escaped = Regexp.escape(Goodmail.config.company_url)
    # Regex to match the typical alt text pattern for a linked logo image
    logo_alt_pattern = /^\s*#{company_name_escaped}\s+Logo\s*\(.*?#{company_url_escaped}.*?\).*\n?/i
    generated_plain_text.gsub!(logo_alt_pattern, "")
  end

  # 5.2. Remove any remaining standalone URL lines (often from logo links or similar artifacts)
  # This targets lines that consist *only* of a URL.
  generated_plain_text.gsub!(/^\s*https?:\/\/\S+\s*$\n?/i, "")

  # 5.3. Compact excess blank lines (more than two consecutive newlines)
  generated_plain_text.gsub!(/\n{3,}/, "\n\n")

  # 6. Return the structured parts
  EmailParts.new(html: final_inlined_html, text: generated_plain_text.strip)
end