Module: MailCatcher::Mail

Extended by:
Mail
Included in:
Mail
Defined in:
lib/mail_catcher/mail.rb

Instance Method Summary collapse

Instance Method Details

#add_message(message) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/mail_catcher/mail.rb', line 44

def add_message(message)
  @add_message_query ||= db.prepare("INSERT INTO message (sender, recipients, subject, source, type, size, created_at) VALUES (?, ?, ?, ?, ?, ?, datetime('now'))")

  mail = Mail.new(message[:source])
  @add_message_query.execute(message[:sender], JSON.generate(message[:recipients]), mail.subject, message[:source], mail.mime_type || "text/plain", message[:source].length)
  message_id = db.last_insert_row_id
  parts = mail.all_parts
  parts = [mail] if parts.empty?
  parts.each do |part|
    body = part.body.to_s
    # Only parts have CIDs, not mail
    cid = part.cid if part.respond_to? :cid
    add_message_part(message_id, cid, part.mime_type || "text/plain", part.attachment? ? 1 : 0, part.filename, part.charset, body, body.length)
  end

  EventMachine.next_tick do
    message = MailCatcher::Mail.message message_id
    MailCatcher::Bus.push(type: "add", message: message)
  end
end

#add_message_part(*args) ⇒ Object



65
66
67
68
# File 'lib/mail_catcher/mail.rb', line 65

def add_message_part(*args)
  @add_message_part_query ||= db.prepare "INSERT INTO message_part (message_id, cid, type, is_attachment, filename, charset, body, size, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))"
  @add_message_part_query.execute(*args)
end

#dbObject



9
10
11
12
13
14
15
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
# File 'lib/mail_catcher/mail.rb', line 9

def db
  @__db ||= begin
    SQLite3::Database.new(":memory:", :type_translation => true).tap do |db|
      db.execute(<<-SQL)
        CREATE TABLE message (
          id INTEGER PRIMARY KEY ASC,
          sender TEXT,
          recipients TEXT,
          subject TEXT,
          source BLOB,
          size TEXT,
          type TEXT,
          created_at DATETIME DEFAULT CURRENT_DATETIME
        )
      SQL
      db.execute(<<-SQL)
        CREATE TABLE message_part (
          id INTEGER PRIMARY KEY ASC,
          message_id INTEGER NOT NULL,
          cid TEXT,
          type TEXT,
          is_attachment INTEGER,
          filename TEXT,
          charset TEXT,
          body BLOB,
          size INTEGER,
          created_at DATETIME DEFAULT CURRENT_DATETIME,
          FOREIGN KEY (message_id) REFERENCES message (id) ON DELETE CASCADE
        )
      SQL
      db.execute("PRAGMA foreign_keys = ON")
    end
  end
end

#delete!Object



156
157
158
159
160
161
162
163
# File 'lib/mail_catcher/mail.rb', line 156

def delete!
  @delete_all_messages_query ||= db.prepare "DELETE FROM message"
  @delete_all_messages_query.execute

  EventMachine.next_tick do
    MailCatcher::Bus.push(type: "clear")
  end
end

#delete_message!(message_id) ⇒ Object



165
166
167
168
169
170
171
172
# File 'lib/mail_catcher/mail.rb', line 165

def delete_message!(message_id)
  @delete_messages_query ||= db.prepare "DELETE FROM message WHERE id = ?"
  @delete_messages_query.execute(message_id)

  EventMachine.next_tick do
    MailCatcher::Bus.push(type: "remove", id: message_id)
  end
end

#delete_older_messages!(count = ) ⇒ Object



174
175
176
177
178
179
180
181
182
# File 'lib/mail_catcher/mail.rb', line 174

def delete_older_messages!(count = MailCatcher.options[:messages_limit])
  return if count.nil?
  @older_messages_query ||= db.prepare "SELECT id FROM message WHERE id NOT IN (SELECT id FROM message ORDER BY created_at DESC LIMIT ?)"
  @older_messages_query.execute(count).map do |row|
    Hash[row.fields.zip(row)]
  end.each do |message|
    delete_message!(message["id"])
  end
end

#latest_created_atObject



70
71
72
73
# File 'lib/mail_catcher/mail.rb', line 70

def latest_created_at
  @latest_created_at_query ||= db.prepare "SELECT created_at FROM message ORDER BY created_at DESC LIMIT 1"
  @latest_created_at_query.execute.next
end

#message(id) ⇒ Object



84
85
86
87
88
89
90
# File 'lib/mail_catcher/mail.rb', line 84

def message(id)
  @message_query ||= db.prepare "SELECT id, sender, recipients, subject, size, type, created_at FROM message WHERE id = ? LIMIT 1"
  row = @message_query.execute(id).next
  row && Hash[row.fields.zip(row)].tap do |message|
    message["recipients"] &&= JSON.parse(message["recipients"])
  end
end

#message_attachments(id) ⇒ Object



115
116
117
118
119
120
# File 'lib/mail_catcher/mail.rb', line 115

def message_attachments(id)
  @message_parts_query ||= db.prepare "SELECT cid, type, filename, size FROM message_part WHERE message_id = ? AND is_attachment = 1 ORDER BY filename ASC"
  @message_parts_query.execute(id).map do |row|
    Hash[row.fields.zip(row)]
  end
end

#message_has_html?(id) ⇒ Boolean

Returns:

  • (Boolean)


98
99
100
101
# File 'lib/mail_catcher/mail.rb', line 98

def message_has_html?(id)
  @message_has_html_query ||= db.prepare "SELECT 1 FROM message_part WHERE message_id = ? AND is_attachment = 0 AND type IN ('application/xhtml+xml', 'text/html') LIMIT 1"
  (!!@message_has_html_query.execute(id).next) || ["text/html", "application/xhtml+xml"].include?(message(id)["type"])
end

#message_has_plain?(id) ⇒ Boolean

Returns:

  • (Boolean)


103
104
105
106
# File 'lib/mail_catcher/mail.rb', line 103

def message_has_plain?(id)
  @message_has_plain_query ||= db.prepare "SELECT 1 FROM message_part WHERE message_id = ? AND is_attachment = 0 AND type = 'text/plain' LIMIT 1"
  (!!@message_has_plain_query.execute(id).next) || message(id)["type"] == "text/plain"
end

#message_part(message_id, part_id) ⇒ Object



122
123
124
125
126
# File 'lib/mail_catcher/mail.rb', line 122

def message_part(message_id, part_id)
  @message_part_query ||= db.prepare "SELECT * FROM message_part WHERE message_id = ? AND id = ? LIMIT 1"
  row = @message_part_query.execute(message_id, part_id).next
  row && Hash[row.fields.zip(row)]
end

#message_part_cid(message_id, cid) ⇒ Object



147
148
149
150
151
152
153
154
# File 'lib/mail_catcher/mail.rb', line 147

def message_part_cid(message_id, cid)
  @message_part_cid_query ||= db.prepare "SELECT * FROM message_part WHERE message_id = ?"
  @message_part_cid_query.execute(message_id).map do |row|
    Hash[row.fields.zip(row)]
  end.find do |part|
    part["cid"] == cid
  end
end

#message_part_html(message_id) ⇒ Object



134
135
136
137
138
139
140
141
# File 'lib/mail_catcher/mail.rb', line 134

def message_part_html(message_id)
  part = message_part_type(message_id, "text/html")
  part ||= message_part_type(message_id, "application/xhtml+xml")
  part ||= begin
    message = message(message_id)
    message if message and ["text/html", "application/xhtml+xml"].include? message["type"]
  end
end

#message_part_plain(message_id) ⇒ Object



143
144
145
# File 'lib/mail_catcher/mail.rb', line 143

def message_part_plain(message_id)
  message_part_type message_id, "text/plain"
end

#message_part_type(message_id, part_type) ⇒ Object



128
129
130
131
132
# File 'lib/mail_catcher/mail.rb', line 128

def message_part_type(message_id, part_type)
  @message_part_type_query ||= db.prepare "SELECT * FROM message_part WHERE message_id = ? AND type = ? AND is_attachment = 0 LIMIT 1"
  row = @message_part_type_query.execute(message_id, part_type).next
  row && Hash[row.fields.zip(row)]
end

#message_parts(id) ⇒ Object



108
109
110
111
112
113
# File 'lib/mail_catcher/mail.rb', line 108

def message_parts(id)
  @message_parts_query ||= db.prepare "SELECT cid, type, filename, size FROM message_part WHERE message_id = ? ORDER BY filename ASC"
  @message_parts_query.execute(id).map do |row|
    Hash[row.fields.zip(row)]
  end
end

#message_source(id) ⇒ Object



92
93
94
95
96
# File 'lib/mail_catcher/mail.rb', line 92

def message_source(id)
  @message_source_query ||= db.prepare "SELECT source FROM message WHERE id = ? LIMIT 1"
  row = @message_source_query.execute(id).next
  row && row.first
end

#messagesObject



75
76
77
78
79
80
81
82
# File 'lib/mail_catcher/mail.rb', line 75

def messages
  @messages_query ||= db.prepare "SELECT id, sender, recipients, subject, size, created_at FROM message ORDER BY created_at, id ASC"
  @messages_query.execute.map do |row|
    Hash[row.fields.zip(row)].tap do |message|
      message["recipients"] &&= JSON.parse(message["recipients"])
    end
  end
end