email_build_test.rb 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. require 'test_helper'
  2. class EmailBuildTest < ActiveSupport::TestCase
  3. test 'document complete check' do
  4. html = '<b>test</b>'
  5. result = Channel::EmailBuild.html_complete_check(html)
  6. assert(result =~ /^<\!DOCTYPE/, 'test 1')
  7. assert(result !~ /^.+?<\!DOCTYPE/, 'test 1')
  8. assert(result =~ /<html>/, 'test 1')
  9. assert(result =~ /font-family/, 'test 1')
  10. assert(result =~ %r{<b>test</b>}, 'test 1')
  11. html = 'invalid <!DOCTYPE html><html><b>test</b></html>'
  12. result = Channel::EmailBuild.html_complete_check(html)
  13. assert(result !~ /^<\!DOCTYPE/, 'test 2')
  14. assert(result =~ /^.+?<\!DOCTYPE/, 'test 2')
  15. assert(result =~ /<html>/, 'test 2')
  16. assert(result !~ /font-family/, 'test 2')
  17. assert(result =~ %r{<b>test</b>}, 'test 2')
  18. # Issue #1230, missing backslashes
  19. # 'Test URL: \\storage\project\100242-Inc'
  20. html = '<b>Test URL</b>: \\\\storage\\project\\100242-Inc'
  21. result = Channel::EmailBuild.html_complete_check(html)
  22. assert(result.include?(html), 'backslashes must be kept')
  23. end
  24. test 'html email + attachment check' do
  25. html = '<!DOCTYPE html>
  26. <html>
  27. <head>
  28. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
  29. </head>
  30. <body style="font-family:Geneva,Helvetica,Arial,sans-serif; font-size: 12px;">
  31. <div>&gt; Welcome!</div><div>&gt;</div><div>&gt; Thank you for installing Zammad. äöüß</div><div>&gt;</div>
  32. </body>
  33. </html>'
  34. mail = Channel::EmailBuild.build(
  35. from: 'sender@example.com',
  36. to: 'recipient@example.com',
  37. body: html,
  38. content_type: 'text/html',
  39. attachments: [
  40. {
  41. 'Mime-Type' => 'image/png',
  42. :content => 'xxx',
  43. :filename => 'somename.png'
  44. }
  45. ],
  46. )
  47. should = '> Welcome!
  48. >
  49. > Thank you for installing Zammad. äöüß
  50. >'
  51. assert_equal(should, mail.text_part.body.to_s)
  52. assert_equal(html, mail.html_part.body.to_s)
  53. parser = Channel::EmailParser.new
  54. data = parser.parse(mail.to_s)
  55. # check body
  56. should = '<div>&gt; Welcome!</div><div>&gt;</div><div>&gt; Thank you for installing Zammad. äöüß</div><div>&gt;</div>'
  57. assert_equal(should, data[:body])
  58. assert_equal('text/html', data[:content_type])
  59. # check count of attachments, only 2, because 3 part is text message and is already in body
  60. assert_equal(2, data[:attachments].length)
  61. # check attachments
  62. data[:attachments]&.each do |attachment|
  63. if attachment[:filename] == 'message.html'
  64. assert_nil(attachment[:preferences]['Content-ID'])
  65. assert_equal(true, attachment[:preferences]['content-alternative'])
  66. assert_equal('text/html', attachment[:preferences]['Mime-Type'])
  67. assert_equal('UTF-8', attachment[:preferences]['Charset'])
  68. elsif attachment[:filename] == 'somename.png'
  69. assert_nil(attachment[:preferences]['Content-ID'])
  70. assert_nil(attachment[:preferences]['content-alternative'])
  71. assert_equal('image/png', attachment[:preferences]['Mime-Type'])
  72. assert_equal('UTF-8', attachment[:preferences]['Charset'])
  73. else
  74. assert(false, "invalid attachment, should not be there, #{attachment.inspect}")
  75. end
  76. end
  77. end
  78. test 'plain email + attachment check' do
  79. text = '> Welcome!
  80. >
  81. > Thank you for installing Zammad. äöüß
  82. >'
  83. mail = Channel::EmailBuild.build(
  84. from: 'sender@example.com',
  85. to: 'recipient@example.com',
  86. body: text,
  87. attachments: [
  88. {
  89. 'Mime-Type' => 'image/png',
  90. :content => 'xxx',
  91. :filename => 'somename.png'
  92. }
  93. ],
  94. )
  95. should = '> Welcome!
  96. >
  97. > Thank you for installing Zammad. äöüß
  98. >'
  99. assert_equal(should, mail.text_part.body.to_s)
  100. assert_nil(mail.html_part)
  101. assert_equal('image/png; filename=somename.png', mail.attachments[0].content_type)
  102. parser = Channel::EmailParser.new
  103. data = parser.parse(mail.to_s)
  104. # check body
  105. assert_equal(should, data[:body])
  106. # check count of attachments, 2
  107. assert_equal(1, data[:attachments].length)
  108. # check attachments
  109. data[:attachments]&.each do |attachment|
  110. if attachment[:filename] == 'somename.png'
  111. assert_nil(attachment[:preferences]['Content-ID'])
  112. assert_nil(attachment[:preferences]['content-alternative'])
  113. assert_equal('image/png', attachment[:preferences]['Mime-Type'])
  114. assert_equal('UTF-8', attachment[:preferences]['Charset'])
  115. else
  116. assert(false, "invalid attachment, should not be there, #{attachment.inspect}")
  117. end
  118. end
  119. end
  120. test 'plain email + attachment check 2' do
  121. ticket1 = Ticket.create!(
  122. title: 'some article helper test1',
  123. group: Group.lookup(name: 'Users'),
  124. customer_id: 2,
  125. state: Ticket::State.lookup(name: 'new'),
  126. priority: Ticket::Priority.lookup(name: '2 normal'),
  127. updated_by_id: 1,
  128. created_by_id: 1,
  129. )
  130. assert(ticket1, 'ticket created')
  131. # create inbound article #1
  132. article1 = Ticket::Article.create!(
  133. ticket_id: ticket1.id,
  134. from: 'some_sender@example.com',
  135. to: 'some_recipient@example.com',
  136. subject: 'some subject',
  137. message_id: 'some@id',
  138. content_type: 'text/html',
  139. body: 'some message article helper test1 <div><img style="width: 85.5px; height: 49.5px" src="cid:15.274327094.140938@zammad.example.com">asdasd<img src="cid:15.274327094.140939@zammad.example.com"><br>',
  140. internal: false,
  141. sender: Ticket::Article::Sender.find_by(name: 'Customer'),
  142. type: Ticket::Article::Type.find_by(name: 'email'),
  143. updated_by_id: 1,
  144. created_by_id: 1,
  145. )
  146. store1 = Store.add(
  147. object: 'Ticket::Article',
  148. o_id: article1.id,
  149. data: 'content_file1_normally_should_be_an_ics_calendar_file',
  150. filename: 'schedule.ics',
  151. preferences: {
  152. 'Mime-Type' => 'text/calendar'
  153. },
  154. created_by_id: 1,
  155. )
  156. text = '> Welcome!
  157. >
  158. > Thank you for installing Zammad. äöüß
  159. >'
  160. mail = Channel::EmailBuild.build(
  161. from: 'sender@example.com',
  162. to: 'recipient@example.com',
  163. body: text,
  164. attachments: [
  165. store1
  166. ],
  167. )
  168. should = '> Welcome!
  169. >
  170. > Thank you for installing Zammad. äöüß
  171. >'
  172. assert_equal(should, mail.text_part.body.to_s)
  173. assert_nil(mail.html_part)
  174. assert_equal('text/calendar; filename=schedule.ics', mail.attachments[0].content_type)
  175. parser = Channel::EmailParser.new
  176. data = parser.parse(mail.to_s)
  177. # check body
  178. assert_equal(should, data[:body])
  179. # check count of attachments, 2
  180. assert_equal(1, data[:attachments].length)
  181. # check attachments
  182. data[:attachments]&.each do |attachment|
  183. if attachment[:filename] == 'schedule.ics'
  184. assert(attachment[:preferences]['Content-ID'])
  185. assert_nil(attachment[:preferences]['content-alternative'])
  186. assert_equal('text/calendar', attachment[:preferences]['Mime-Type'])
  187. assert_equal('UTF-8', attachment[:preferences]['Charset'])
  188. else
  189. assert(false, "invalid attachment, should not be there, #{attachment.inspect}")
  190. end
  191. end
  192. end
  193. test 'plain email + without attachment check' do
  194. text = '> Welcome!
  195. >
  196. > Thank you for installing Zammad. äöüß
  197. >'
  198. mail = Channel::EmailBuild.build(
  199. from: 'sender@example.com',
  200. to: 'recipient@example.com',
  201. body: text,
  202. )
  203. should = '> Welcome!
  204. >
  205. > Thank you for installing Zammad. äöüß
  206. >'
  207. assert_equal(should, mail.body.to_s)
  208. assert_nil(mail.html_part)
  209. parser = Channel::EmailParser.new
  210. data = parser.parse(mail.to_s)
  211. # check body
  212. assert_equal(should, data[:body])
  213. # check count of attachments, 0
  214. assert_equal(0, data[:attachments].length)
  215. end
  216. test 'email - html email client fixes' do
  217. # https://github.com/martini/zammad/issues/165
  218. html_raw = '<blockquote type="cite">some
  219. text
  220. </blockquote>
  221. 123
  222. <blockquote type="cite">some
  223. text
  224. </blockquote>'
  225. html_with_fixes = Channel::EmailBuild.html_mail_client_fixes(html_raw)
  226. assert_not_equal(html_with_fixes, html_raw)
  227. html_should = '<blockquote type="cite" style="border-left: 2px solid blue; margin: 0 0 16px; padding: 8px 12px 8px 12px;">some
  228. text
  229. </blockquote>
  230. 123
  231. <blockquote type="cite" style="border-left: 2px solid blue; margin: 0 0 16px; padding: 8px 12px 8px 12px;">some
  232. text
  233. </blockquote>'
  234. assert_equal(html_should, html_with_fixes)
  235. html_raw = '<p>some
  236. text
  237. </p>
  238. <p>123</p>'
  239. html_with_fixes = Channel::EmailBuild.html_mail_client_fixes(html_raw)
  240. assert_not_equal(html_with_fixes, html_raw)
  241. html_should = '<p style="margin: 0;">some
  242. text
  243. </p>
  244. <p style="margin: 0;">123</p>'
  245. assert_equal(html_should, html_with_fixes)
  246. html_raw = '<p>sometext</p><hr><p>123</p>'
  247. html_with_fixes = Channel::EmailBuild.html_mail_client_fixes(html_raw)
  248. assert_not_equal(html_with_fixes, html_raw)
  249. html_should = '<p style="margin: 0;">sometext</p><hr style="margin-top: 6px; margin-bottom: 6px; border: 0; border-top: 1px solid #dfdfdf;"><p style="margin: 0;">123</p>'
  250. assert_equal(html_should, html_with_fixes)
  251. end
  252. test 'from checks' do
  253. quoted_in_one_line = Channel::EmailBuild.recipient_line('Somebody @ "Company"', 'some.body@example.com')
  254. assert_equal('"Somebody @ \"Company\"" <some.body@example.com>', quoted_in_one_line)
  255. quoted_in_one_line = Channel::EmailBuild.recipient_line('Somebody', 'some.body@example.com')
  256. assert_equal('Somebody <some.body@example.com>', quoted_in_one_line)
  257. quoted_in_one_line = Channel::EmailBuild.recipient_line('Somebody | Some Org', 'some.body@example.com')
  258. assert_equal('"Somebody | Some Org" <some.body@example.com>', quoted_in_one_line)
  259. quoted_in_one_line = Channel::EmailBuild.recipient_line('Test Master Agent via Support', 'some.body@example.com')
  260. assert_equal('"Test Master Agent via Support" <some.body@example.com>', quoted_in_one_line)
  261. end
  262. end