Class: Tina4::DevMailbox

Inherits:
Object
  • Object
show all
Defined in:
lib/tina4/dev_mailbox.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(mailbox_dir: nil) ⇒ DevMailbox

Returns a new instance of DevMailbox.



13
14
15
16
# File 'lib/tina4/dev_mailbox.rb', line 13

def initialize(mailbox_dir: nil)
  @mailbox_dir = mailbox_dir || ENV["TINA4_MAILBOX_DIR"] || "data/mailbox"
  ensure_dirs
end

Instance Attribute Details

#mailbox_dirObject (readonly)

Returns the value of attribute mailbox_dir.



11
12
13
# File 'lib/tina4/dev_mailbox.rb', line 11

def mailbox_dir
  @mailbox_dir
end

Instance Method Details

#capture(to:, subject:, body:, html: false, cc: [], bcc: [], reply_to: nil, from_address: nil, from_name: nil, attachments: []) ⇒ Object

Capture an outgoing email to the local filesystem instead of sending



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
# File 'lib/tina4/dev_mailbox.rb', line 19

def capture(to:, subject:, body:, html: false, cc: [], bcc: [],
            reply_to: nil, from_address: nil, from_name: nil, attachments: [])
  msg_id = SecureRandom.uuid
  timestamp = Time.now

  message = {
    id: msg_id,
    from: { name: from_name, email: from_address },
    to: normalize_recipients(to),
    cc: normalize_recipients(cc),
    bcc: normalize_recipients(bcc),
    reply_to: reply_to,
    subject: subject,
    body: body,
    html: html,
    attachments: store_attachments(msg_id, attachments),
    read: false,
    folder: "outbox",
    created_at: timestamp.strftime("%Y-%m-%dT%H:%M:%S.%6N%:z"),
    updated_at: timestamp.iso8601
  }

  write_message(msg_id, message)

  Tina4::Log.debug("DevMailbox captured email: #{subject} -> #{Array(to).join(', ')}")
  { success: true, message: "Email captured to dev mailbox", id: msg_id }
end

#clear(folder: nil) ⇒ Object

Clear all messages, optionally by folder



86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/tina4/dev_mailbox.rb', line 86

def clear(folder: nil)
  if folder
    load_all_messages.each do |msg|
      delete(msg[:id]) if msg[:folder] == folder
    end
  else
    messages_dir = File.join(@mailbox_dir, "messages")
    FileUtils.rm_rf(messages_dir)
    FileUtils.rm_rf(File.join(@mailbox_dir, "attachments"))
    ensure_dirs
  end
end

#count(folder: nil) ⇒ Object

Count messages by folder Returns { inbox: N, outbox: N, total: N }



119
120
121
122
123
124
125
126
127
128
129
# File 'lib/tina4/dev_mailbox.rb', line 119

def count(folder: nil)
  messages = load_all_messages
  if folder
    n = messages.count { |m| m[:folder] == folder }
    { folder.to_sym => n, total: n }
  else
    inbox_count = messages.count { |m| m[:folder] == "inbox" }
    outbox_count = messages.count { |m| m[:folder] == "outbox" }
    { inbox: inbox_count, outbox: outbox_count, total: messages.length }
  end
end

#delete(msg_id) ⇒ Object

Delete a message by ID



74
75
76
77
78
79
80
81
82
83
# File 'lib/tina4/dev_mailbox.rb', line 74

def delete(msg_id)
  path = message_path(msg_id)
  return false unless File.exist?(path)

  File.delete(path)
  # Clean up attachments directory
  att_dir = File.join(@mailbox_dir, "attachments", msg_id)
  FileUtils.rm_rf(att_dir) if Dir.exist?(att_dir)
  true
end

#inbox(limit: 50, offset: 0, folder: nil) ⇒ Object

List messages in the mailbox



48
49
50
51
52
# File 'lib/tina4/dev_mailbox.rb', line 48

def inbox(limit: 50, offset: 0, folder: nil)
  messages = load_all_messages
  messages = messages.select { |m| m[:folder] == folder } if folder
  messages.sort_by { |m| m[:created_at] || "" }.reverse[offset, limit] || []
end

#read(msg_id) ⇒ Object

Read a single message by ID



55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/tina4/dev_mailbox.rb', line 55

def read(msg_id)
  path = message_path(msg_id)
  return nil unless File.exist?(path)

  message = JSON.parse(File.read(path), symbolize_names: true)
  unless message[:read]
    message[:read] = true
    message[:updated_at] = Time.now.iso8601
    File.write(path, JSON.pretty_generate(message))
  end
  message
end

#seed(count: 5) ⇒ Object

Seed the mailbox with sample messages for development



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/tina4/dev_mailbox.rb', line 100

def seed(count: 5)
  fake = Tina4::FakeData.new
  count.times do |i|
    name = fake.name
    email = fake.email(from_name: name)
    capture(
      to: "dev@localhost",
      subject: fake.sentence(words: 4 + rand(4)),
      body: Array.new(2 + rand(3)) { fake.sentence(words: 8 + rand(8)) }.join("\n\n"),
      html: i.even?,
      from_address: email,
      from_name: name
    )
  end
  Tina4::Log.info("DevMailbox seeded with #{count} messages")
end

#unread_countObject

Count unread messages



69
70
71
# File 'lib/tina4/dev_mailbox.rb', line 69

def unread_count
  load_all_messages.count { |m| m[:read] == false }
end