email_parser.rb 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. require 'mail'
  2. require 'iconv'
  3. class Channel::EmailParser
  4. def conv (charset, string)
  5. if charset == 'US-ASCII' || charset == 'ASCII-8BIT'
  6. charset = 'LATIN1'
  7. end
  8. return string if charset.downcase == 'utf8' || charset.downcase == 'utf-8'
  9. # puts '-------' + charset
  10. # puts string
  11. # string.encode("UTF-8")
  12. Iconv.conv( 'UTF8', charset, string )
  13. end
  14. def parse (msg)
  15. data = {}
  16. mail = Mail.new( msg )
  17. # set all headers
  18. mail.header.fields.each { |field|
  19. data[field.name.downcase.to_sym] = field.to_s
  20. }
  21. # set extra headers
  22. data[:from_email] = Mail::Address.new( mail[:from].value ).address
  23. data[:from_local] = Mail::Address.new( mail[:from].value ).local
  24. data[:from_domain] = Mail::Address.new( mail[:from].value ).domain
  25. data[:from_display_name] = Mail::Address.new( mail[:from].value ).display_name
  26. # do extra decoding because we needed to use field.value
  27. data[:from_display_name] = Mail::Field.new( 'X-From', data[:from_display_name] ).to_s
  28. # compat headers
  29. data[:message_id] = data['message-id'.to_sym]
  30. puts data.inspect
  31. # body
  32. # plain_part = mail.multipart? ? (mail.text_part ? mail.text_part.body.decoded : nil) : mail.body.decoded
  33. # html_part = message.html_part ? message.html_part.body.decoded : nil
  34. if mail.multipart?
  35. data[:plain_part] = mail.text_part.body.decoded
  36. data[:plain_part] = conv( mail.text_part.charset || 'LATIN1', data[:plain_part] )
  37. else
  38. data[:plain_part] = mail.body.decoded
  39. data[:plain_part] = conv( mail.body.charset || 'LATIN1', data[:plain_part] )
  40. end
  41. # attachments
  42. if mail.attachments
  43. data[:attachments] = []
  44. mail.attachments.each do |attachment|
  45. # get file preferences
  46. headers = {}
  47. attachment.header.fields.each do |f|
  48. headers[f.name] = f.value
  49. end
  50. headers_store = {}
  51. headers_store['Mime-Type'] = attachment.mime_type
  52. if attachment.charset
  53. headers_store['Charset'] = attachment.charset
  54. end
  55. ['Content-ID', 'Content-Type'].each do |item|
  56. if headers[item]
  57. headers_store[item] = headers[item]
  58. end
  59. end
  60. attachment = {
  61. :data => attachment.body.decoded,
  62. :filename => attachment.filename,
  63. :preferences => headers_store
  64. }
  65. data[:attachments].push attachment
  66. end
  67. end
  68. return data
  69. end
  70. def process(channel, msg)
  71. mail = parse( msg )
  72. # use transaction
  73. ActiveRecord::Base.transaction do
  74. user = User.where( :email => mail[:from_email] ).first
  75. if !user then
  76. puts 'create user...'
  77. roles = Role.where( :name => 'Customer' )
  78. user = User.create(
  79. :login => mail[:from_email],
  80. :firstname => mail[:from_display_name],
  81. :lastname => '',
  82. :email => mail[:from_email],
  83. :password => '',
  84. :active => true,
  85. :roles => roles,
  86. :created_by_id => 1
  87. )
  88. end
  89. # set current user
  90. UserInfo.current_user_id = user.id
  91. # get ticket# from subject
  92. ticket = Ticket.number_check( mail[:subject] )
  93. # set ticket state to open if not new
  94. if ticket
  95. ticket_state = Ticket::State.find( ticket.ticket_state_id )
  96. ticket_state_type = Ticket::StateType.find( ticket_state.ticket_state_type_id )
  97. if ticket_state_type.name != 'new'
  98. ticket.ticket_state = Ticket::State.where( :name => 'open' ).first
  99. ticket.save
  100. end
  101. end
  102. # create new ticket
  103. if !ticket then
  104. ticket = Ticket.create(
  105. :group_id => channel[:group_id] || 1,
  106. :customer_id => user.id,
  107. :title => mail[:subject],
  108. :ticket_state_id => Ticket::State.where(:name => 'new').first.id,
  109. :ticket_priority_id => Ticket::Priority.where(:name => '2 normal').first.id,
  110. :created_by_id => user.id
  111. )
  112. end
  113. # import mail
  114. article = Ticket::Article.create(
  115. :created_by_id => user.id,
  116. :ticket_id => ticket.id,
  117. :ticket_article_type_id => Ticket::Article::Type.where(:name => 'email').first.id,
  118. :ticket_article_sender_id => Ticket::Article::Sender.where(:name => 'Customer').first.id,
  119. :body => mail[:plain_part],
  120. :from => mail[:from],
  121. :to => mail[:to],
  122. :cc => mail[:cc],
  123. :subject => mail[:subject],
  124. :message_id => mail[:message_id],
  125. :internal => false
  126. )
  127. # store mail plain
  128. Store.add(
  129. :object => 'Ticket::Article::Mail',
  130. :o_id => article.id,
  131. :data => msg,
  132. :filename => 'plain.msg',
  133. :preferences => {}
  134. )
  135. # store attachments
  136. if mail[:attachments]
  137. mail[:attachments].each do |attachment|
  138. Store.add(
  139. :object => 'Ticket::Article',
  140. :o_id => article.id,
  141. :data => attachment[:data],
  142. :filename => attachment[:filename],
  143. :preferences => attachment[:preferences]
  144. )
  145. end
  146. end
  147. return ticket, article, user
  148. end
  149. # execute ticket events
  150. Ticket::Observer::Notification.transaction
  151. end
  152. end