2010-10-27 15:12:26 -04:00
require 'mail'
require 'sqlite3'
require 'eventmachine'
module MailCatcher::Mail
class << self
def db
@@__db || = begin
2011-05-29 08:26:15 -04:00
SQLite3 :: Database . new ( ':memory:' , :type_translation = > true ) . tap do | db |
2010-10-27 15:12:26 -04:00
db . execute ( <<-SQL)
CREATE TABLE message (
id INTEGER PRIMARY KEY ASC ,
sender TEXT ,
recipients TEXT ,
subject TEXT ,
source BLOB ,
size TEXT ,
2011-05-29 09:16:33 -04:00
type TEXT ,
2010-10-27 15:12:26 -04:00
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
)
SQL
end
end
end
def add_message ( message )
2011-05-29 09:16:33 -04:00
@@add_message_query || = db . prepare ( " INSERT INTO message (sender, recipients, subject, source, type, size, created_at) VALUES (?, ?, ?, ?, ?, ?, datetime('now')) " )
2010-10-27 15:12:26 -04:00
mail = Mail . new ( message [ :source ] )
2011-05-29 09:16:33 -04:00
result = @@add_message_query . execute ( message [ :sender ] , message [ :recipients ] . to_json , mail . subject , message [ :source ] , mail . mime_type || 'text/plain' , message [ :source ] . length )
2010-10-27 15:12:26 -04:00
message_id = db . last_insert_row_id
2011-05-09 23:26:42 -04:00
parts = mail . all_parts
parts = [ mail ] if parts . empty?
parts . each do | part |
2010-10-27 15:12:26 -04:00
body = part . body . to_s
2010-11-04 00:48:06 -04:00
# 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 )
2010-10-27 15:12:26 -04:00
end
EventMachine . next_tick do
message = MailCatcher :: Mail . message message_id
MailCatcher :: Events :: MessageAdded . push message
end
end
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
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
def messages
@@messages_query || = db . prepare " SELECT id, sender, recipients, subject, size, created_at FROM message ORDER BY created_at DESC "
2011-05-29 08:26:15 -04:00
@@messages_query . execute . map do | row |
Hash [ row . fields . zip ( row ) ] . tap do | message |
2011-05-27 10:10:05 -04:00
message [ " recipients " ] && = ActiveSupport :: JSON . decode message [ " recipients " ]
end
end
2010-10-27 15:12:26 -04:00
end
def message ( id )
@@message_query || = db . prepare " SELECT * FROM message WHERE id = ? LIMIT 1 "
2011-05-29 08:26:15 -04:00
row = @@message_query . execute ( id ) . next
row && Hash [ row . fields . zip ( row ) ] . tap do | message |
2011-05-27 10:10:05 -04:00
message [ " recipients " ] && = ActiveSupport :: JSON . decode message [ " recipients " ]
end
2010-10-27 15:12:26 -04:00
end
def message_has_html? ( id )
2011-05-29 09:16:33 -04:00
@@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 " ] )
2010-10-27 15:12:26 -04:00
end
def message_has_plain? ( id )
2011-05-29 09:16:33 -04:00
@@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 "
2010-10-27 15:12:26 -04:00
end
def message_parts ( id )
@@message_parts_query || = db . prepare " SELECT cid, type, filename, size FROM message_part WHERE message_id = ? ORDER BY filename ASC "
2011-05-29 08:26:15 -04:00
@@message_parts_query . execute ( id ) . map do | row |
Hash [ row . fields . zip ( row ) ]
end
2010-10-27 15:12:26 -04:00
end
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 "
2011-05-29 08:26:15 -04:00
@@message_parts_query . execute ( id ) . map do | row |
Hash [ row . fields . zip ( row ) ]
end
2010-10-27 15:12:26 -04:00
end
def message_part ( message_id , part_id )
@@message_part_query || = db . prepare " SELECT * FROM message_part WHERE message_id = ? AND id = ? LIMIT 1 "
2011-05-29 08:26:15 -04:00
row = @@message_part_query . execute ( message_id , part_id ) . next
row && Hash [ row . fields . zip ( row ) ]
2010-10-27 15:12:26 -04:00
end
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 "
2011-05-29 08:26:15 -04:00
row = @@message_part_type_query . execute ( message_id , part_type ) . next
row && Hash [ row . fields . zip ( row ) ]
2010-10-27 15:12:26 -04:00
end
def message_part_html ( message_id )
2011-05-29 09:16:33 -04:00
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 [ 'text/html' , 'application/xhtml+xml' ] . include? message [ " type " ]
end
2010-10-27 15:12:26 -04:00
end
def message_part_plain ( message_id )
message_part_type message_id , " text/plain "
end
def message_part_cid ( message_id , cid )
@@message_part_cid_query || = db . prepare 'SELECT * FROM message_part WHERE message_id = ?'
2011-05-29 08:26:15 -04:00
@@message_part_cid_query . execute ( message_id ) . map do | row |
part = Hash [ row . fields . zip ( row ) ]
end . find do | part |
part [ " cid " ] == cid
end
2010-10-27 15:12:26 -04:00
end
end
end