email_process_follow_up_test.rb 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  1. require 'test_helper'
  2. class EmailProcessFollowUpTest < ActiveSupport::TestCase
  3. test 'process with follow up check' do
  4. ticket = Ticket.create(
  5. title: 'follow up check',
  6. group: Group.lookup(name: 'Users'),
  7. customer_id: 2,
  8. state: Ticket::State.lookup(name: 'new'),
  9. priority: Ticket::Priority.lookup(name: '2 normal'),
  10. updated_by_id: 1,
  11. created_by_id: 1,
  12. )
  13. article = Ticket::Article.create(
  14. ticket_id: ticket.id,
  15. from: 'some_sender@example.com',
  16. to: 'some_recipient@example.com',
  17. subject: 'follow up check',
  18. message_id: '<20150830145601.30.608882@edenhofer.zammad.com>',
  19. body: 'some message article',
  20. internal: false,
  21. sender: Ticket::Article::Sender.lookup(name: 'Agent'),
  22. type: Ticket::Article::Type.lookup(name: 'email'),
  23. updated_by_id: 1,
  24. created_by_id: 1,
  25. )
  26. email_raw_string_subject = "From: me@example.com
  27. To: customer@example.com
  28. Subject: #{ticket.subject_build('some new subject')}
  29. Some Text"
  30. email_raw_string_other_subject = "From: me@example.com
  31. To: customer@example.com
  32. Subject: other subject #{Setting.get('ticket_hook')}#{ticket.number}
  33. Some Text"
  34. email_raw_string_body = "From: me@example.com
  35. To: customer@example.com
  36. Subject: no reference
  37. Some Text #{ticket.subject_build('some new subject')} "
  38. email_raw_string_attachment = "From: me@example.com
  39. Content-Type: multipart/mixed; boundary=\"Apple-Mail=_ED77AC8D-FB6F-40E5-8FBE-D41FF5E1BAF2\"
  40. Subject: no reference
  41. Date: Sun, 30 Aug 2015 23:20:54 +0200
  42. To: Martin Edenhofer <me@znuny.com>
  43. Mime-Version: 1.0 (Mac OS X Mail 8.2 \(2104\))
  44. X-Mailer: Apple Mail (2.2104)
  45. --Apple-Mail=_ED77AC8D-FB6F-40E5-8FBE-D41FF5E1BAF2
  46. Content-Transfer-Encoding: 7bit
  47. Content-Type: text/plain;
  48. charset=us-ascii
  49. no reference
  50. --Apple-Mail=_ED77AC8D-FB6F-40E5-8FBE-D41FF5E1BAF2
  51. Content-Disposition: attachment;
  52. filename=test1.txt
  53. Content-Type: text/plain;
  54. name=\"test.txt\"
  55. Content-Transfer-Encoding: 7bit
  56. Some Text #{ticket.subject_build('some new subject')}
  57. --Apple-Mail=_ED77AC8D-FB6F-40E5-8FBE-D41FF5E1BAF2--"
  58. email_raw_string_references1 = "From: me@example.com
  59. To: customer@example.com
  60. Subject: no reference
  61. In-Reply-To: <20150830145601.30.608882@edenhofer.zammad.com>
  62. References: <DA918CD1-BE9A-4262-ACF6-5001E59291B6@znuny.com>
  63. no reference "
  64. email_raw_string_references2 = "From: me@example.com
  65. To: customer@example.com
  66. Subject: no reference
  67. References: <DA918CD1-BE9A-4262-ACF6-5001E59291B6@znuny.com> <20150830145601.30.608882@edenhofer.zammad.com> <DA918CD1-BE9A-4262-ACF6-5001E59291XX@znuny.com>
  68. no reference "
  69. setting_orig = Setting.get('postmaster_follow_up_search_in')
  70. Setting.set('postmaster_follow_up_search_in', %w[body attachment references])
  71. travel 1.second
  72. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_subject)
  73. assert_equal(ticket.id, ticket_p.id)
  74. travel 1.second
  75. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_other_subject)
  76. assert_equal(ticket.id, ticket_p.id)
  77. travel 1.second
  78. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_body)
  79. assert_equal(ticket.id, ticket_p.id)
  80. travel 1.second
  81. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_attachment)
  82. assert_equal(ticket.id, ticket_p.id)
  83. travel 1.second
  84. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_references1)
  85. assert_equal(ticket.id, ticket_p.id)
  86. travel 1.second
  87. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_references2)
  88. assert_equal(ticket.id, ticket_p.id)
  89. Setting.set('postmaster_follow_up_search_in', nil)
  90. travel 1.second
  91. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_subject)
  92. assert_equal(ticket.id, ticket_p.id)
  93. travel 1.second
  94. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_other_subject)
  95. assert_equal(ticket.id, ticket_p.id)
  96. travel 1.second
  97. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_body)
  98. assert_not_equal(ticket.id, ticket_p.id)
  99. travel 1.second
  100. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_attachment)
  101. assert_not_equal(ticket.id, ticket_p.id)
  102. travel 1.second
  103. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_references1)
  104. assert_not_equal(ticket.id, ticket_p.id)
  105. travel 1.second
  106. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_references2)
  107. assert_not_equal(ticket.id, ticket_p.id)
  108. Setting.set('postmaster_follow_up_search_in', 'references')
  109. travel 1.second
  110. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_subject)
  111. assert_equal(ticket.id, ticket_p.id)
  112. travel 1.second
  113. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_other_subject)
  114. assert_equal(ticket.id, ticket_p.id)
  115. travel 1.second
  116. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_body)
  117. assert_not_equal(ticket.id, ticket_p.id)
  118. travel 1.second
  119. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_attachment)
  120. assert_not_equal(ticket.id, ticket_p.id)
  121. travel 1.second
  122. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_references1)
  123. assert_equal(ticket.id, ticket_p.id)
  124. travel 1.second
  125. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_references2)
  126. assert_equal(ticket.id, ticket_p.id)
  127. Setting.set('postmaster_follow_up_search_in', setting_orig)
  128. travel 1.second
  129. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_subject)
  130. assert_equal(ticket.id, ticket_p.id)
  131. travel 1.second
  132. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_other_subject)
  133. assert_equal(ticket.id, ticket_p.id)
  134. travel 1.second
  135. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_body)
  136. assert_not_equal(ticket.id, ticket_p.id)
  137. travel 1.second
  138. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_attachment)
  139. assert_not_equal(ticket.id, ticket_p.id)
  140. travel 1.second
  141. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_references1)
  142. assert_not_equal(ticket.id, ticket_p.id)
  143. travel 1.second
  144. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_references2)
  145. assert_not_equal(ticket.id, ticket_p.id)
  146. travel_back
  147. end
  148. test 'process with follow up check with different ticket hook' do
  149. Setting.set('ticket_hook', 'VD-Ticket#')
  150. ticket = Ticket.create(
  151. title: 'follow up check ticket hook',
  152. group: Group.lookup(name: 'Users'),
  153. customer_id: 2,
  154. state: Ticket::State.lookup(name: 'new'),
  155. priority: Ticket::Priority.lookup(name: '2 normal'),
  156. updated_by_id: 1,
  157. created_by_id: 1,
  158. )
  159. article = Ticket::Article.create(
  160. ticket_id: ticket.id,
  161. from: 'some_sender@example.com',
  162. to: 'some_recipient@example.com',
  163. subject: 'follow up check',
  164. message_id: '<20150830145601.30.608882.123123@edenhofer.zammad.com>',
  165. body: 'some message article',
  166. internal: false,
  167. sender: Ticket::Article::Sender.lookup(name: 'Agent'),
  168. type: Ticket::Article::Type.lookup(name: 'email'),
  169. updated_by_id: 1,
  170. created_by_id: 1,
  171. )
  172. email_raw_string_subject = "From: me@example.com
  173. To: customer@example.com
  174. Subject: #{ticket.subject_build('some new subject')}
  175. Some Text"
  176. email_raw_string_other_subject = "From: me@example.com
  177. To: customer@example.com
  178. Subject: Aw: RE: other subject [#{Setting.get('ticket_hook')}#{ticket.number}]
  179. Some Text"
  180. travel 1.second
  181. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_subject)
  182. assert_equal(ticket.id, ticket_p.id)
  183. travel 1.second
  184. ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_other_subject)
  185. assert_equal(ticket.id, ticket_p.id)
  186. travel_back
  187. end
  188. test 'process with follow up check with two external reference headers' do
  189. Setting.set('postmaster_follow_up_search_in', %w[body attachment references])
  190. data1 = "From: me@example.com
  191. To: z@example.com
  192. Subject: test 123
  193. Message-ID: <9d16181c-2db2-c6c1-ff7f-41f2da4e289a@linuxhotel.de>
  194. test 123
  195. "
  196. ticket_p1, article_p1, user_p1 = Channel::EmailParser.new.process({}, data1)
  197. travel 1.second
  198. data1 = "From: me@example.com
  199. To: z@example.com
  200. Subject: test 123
  201. Message-ID: <9d16181c-2db2-c6c1-ff7f-41f2da4e289a@linuxhotel.de>
  202. test 123
  203. "
  204. ticket_p2, article_p2, user_p2 = Channel::EmailParser.new.process({}, data1)
  205. assert_not_equal(ticket_p1.id, ticket_p2.id)
  206. data2 = "From: you@example.com
  207. To: y@example.com
  208. Subject: RE: test 123
  209. Message-ID: <oknn9teOke2uqbFQdGj2umXUwTkqgu0CqWHkA6V4K8p@akmail>
  210. References: <9d16181c-2db2-c6c1-ff7f-41f2da4e289a@linuxhotel.de>
  211. test 123
  212. "
  213. ticket_p3, article_p3, user_p3 = Channel::EmailParser.new.process({}, data2)
  214. assert_equal(ticket_p2.id, ticket_p3.id)
  215. travel_back
  216. end
  217. test 'process with follow up check - with auto responses and no T# in subject_build' do
  218. ticket = Ticket.create(
  219. title: 'follow up - with references follow up check',
  220. group: Group.lookup(name: 'Users'),
  221. customer_id: 2,
  222. state: Ticket::State.lookup(name: 'closed'),
  223. priority: Ticket::Priority.lookup(name: '2 normal'),
  224. updated_by_id: 1,
  225. created_by_id: 1,
  226. )
  227. article = Ticket::Article.create(
  228. ticket_id: ticket.id,
  229. from: 'some_sender@example.com',
  230. to: 'some_recipient@example.com',
  231. subject: 'follow up with references follow up check',
  232. message_id: '<20151222145601.30.608881@edenhofer.zammad.com>',
  233. body: 'some message with references follow up check',
  234. internal: false,
  235. sender: Ticket::Article::Sender.lookup(name: 'Agent'),
  236. type: Ticket::Article::Type.lookup(name: 'email'),
  237. updated_by_id: 1,
  238. created_by_id: 1,
  239. )
  240. travel 1.second
  241. # auto response without T# in subject, find follow up by references header
  242. email_raw_string = "From: bob@example.com
  243. To: customer@example.com
  244. Subject: =?ISO-8859-1?Q?AUTO=3A_Bob_Smith_ist_au=DFer_Haus=2E_=2F_is_out_of?=
  245. =?ISO-8859-1?Q?_office=2E_=28R=FCckkehr_am_28=2E12=2E2015=29?=
  246. In-Reply-To: <20251222081758.116249.983698@portal.znuny.com>
  247. References: <OF9D1FD72A.878EF84E-ONC1257F22.003D7BB4-C1257F22.003F4503@example.com> <20151222145601.30.608881@edenhofer.zammad.com> <20251222081758.116249.983698@portal.znuny.com>
  248. Message-ID: <OFD563742F.FC05EEAF-ONC1257F23.002DAE02@example.com>
  249. Auto-Submitted: auto-replied
  250. Some Text"
  251. ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
  252. ticket = Ticket.find(ticket.id)
  253. assert_equal(ticket.id, ticket_p.id)
  254. assert_equal('open', ticket.state.name)
  255. travel_back
  256. end
  257. test 'process with follow up check - email with more forgein T#\'s in subject' do
  258. ticket = Ticket.create(
  259. title: 'email with more forgein T#\'s in subject',
  260. group: Group.lookup(name: 'Users'),
  261. customer_id: 2,
  262. state: Ticket::State.lookup(name: 'closed'),
  263. priority: Ticket::Priority.lookup(name: '2 normal'),
  264. updated_by_id: 1,
  265. created_by_id: 1,
  266. )
  267. article = Ticket::Article.create(
  268. ticket_id: ticket.id,
  269. from: 'some_sender@example.com',
  270. to: 'some_recipient@example.com',
  271. subject: 'follow up with references follow up check',
  272. message_id: '<20151222145601.30.608881@edenhofer.zammad.com>',
  273. body: 'some message with references follow up check',
  274. internal: false,
  275. sender: Ticket::Article::Sender.lookup(name: 'Agent'),
  276. type: Ticket::Article::Type.lookup(name: 'email'),
  277. updated_by_id: 1,
  278. created_by_id: 1,
  279. )
  280. travel 1.second
  281. system_id = Setting.get('system_id')
  282. ticket_hook = Setting.get('ticket_hook')
  283. ticket_hook_divider = Setting.get('ticket_hook_divider')
  284. tn = "[#{ticket_hook}#{ticket_hook_divider}#{system_id}#{Ticket::Number.generate}99]"
  285. email_raw_string_subject = "From: me@example.com
  286. To: customer@example.com
  287. Subject: First foreign Tn #{tn} #{tn} #{tn} - #{ticket.subject_build('some new subject')}
  288. Some Text"
  289. ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string_subject)
  290. ticket = Ticket.find(ticket.id)
  291. assert_equal(ticket.id, ticket_p.id)
  292. assert_equal('open', ticket.state.name)
  293. travel_back
  294. end
  295. test 'process with follow up check - ticket initiated by customer without T# in subject and other people in Cc reply to all' do
  296. # check if follow up based on inital system sender address
  297. Setting.set('postmaster_follow_up_search_in', [])
  298. subject = "ticket initiated by customer without T# in subject and other people in Cc reply to all #{rand(9999)}"
  299. email_raw_string = "From: me@example.com
  300. To: my@system.test, bob@example.com
  301. Subject: #{subject}
  302. Message-ID: <123456789-$follow-up-test§-1@linuxhotel.de>
  303. Some Text"
  304. ticket_p1, article_1, user_1, mail = Channel::EmailParser.new.process({}, email_raw_string)
  305. ticket1 = Ticket.find(ticket_p1.id)
  306. assert_equal(subject, ticket1.title)
  307. # follow up possible because same subject
  308. email_raw_string = "From: bob@example.com
  309. To: my@system.test, me@example.com
  310. Subject: AW: #{subject}
  311. Message-ID: <123456789-$follow-up-test§-2@linuxhotel.de>
  312. References: <123456789-$follow-up-test§-1@linuxhotel.de>
  313. Some Text"
  314. ticket_p2, article_p2, user_p2, mail = Channel::EmailParser.new.process({}, email_raw_string)
  315. ticket2 = Ticket.find(ticket_p2.id)
  316. assert_equal(ticket1.id, ticket2.id)
  317. assert_equal(subject, ticket2.title)
  318. # follow up possible because same subject
  319. email_raw_string = "From: bob@example.com
  320. To: my@system.test, me@example.com
  321. Subject: AW: RE: #{subject}
  322. Message-ID: <123456789-$follow-up-test§-2@linuxhotel.de>
  323. References: <123456789-$follow-up-test§-1@linuxhotel.de>
  324. Some Text"
  325. ticket_p3, article_p3, user_p3, mail = Channel::EmailParser.new.process({}, email_raw_string)
  326. ticket3 = Ticket.find(ticket_p3.id)
  327. assert_equal(ticket1.id, ticket3.id)
  328. assert_equal(subject, ticket3.title)
  329. # follow up not possible because subject has changed
  330. subject = "new subject without ticket ref #{rand(9_999_999)}"
  331. email_raw_string = "From: bob@example.com
  332. To: my@system.test
  333. Subject: #{subject}
  334. Message-ID: <123456789-$follow-up-test§-3@linuxhotel.de>
  335. References: <123456789-$follow-up-test§-1@linuxhotel.de>
  336. Some Text"
  337. ticket_p4, article_p4, user_p4, mail = Channel::EmailParser.new.process({}, email_raw_string)
  338. ticket4 = Ticket.find(ticket_p4.id)
  339. assert_not_equal(ticket1.id, ticket4.id)
  340. assert_equal(subject, ticket4.title)
  341. # usecase with same subject but no Ticket# (reference headers check because of same subject)
  342. subject = 'Embedded Linux 20.03 - 23.03.17'
  343. email_raw_string = "From: iw@example.com
  344. To: customer@example.com
  345. Subject: #{subject}
  346. Message-ID: <b1a84d36-4475-28e8-acde-5c18ebe94182@example.com>
  347. Some Text"
  348. ticket_p5, article_5, user_5, mail = Channel::EmailParser.new.process({}, email_raw_string)
  349. ticket5 = Ticket.find(ticket_p5.id)
  350. assert_not_equal(ticket1.id, ticket5.id)
  351. assert_equal(subject, ticket5.title)
  352. email_raw_string = "From: customer@example.com
  353. To: iw@example.com
  354. Subject: Re: #{subject}
  355. Message-ID: <b1a84d36-4475-28e8-acde-5c18ebe94183@customer.example.com>
  356. In-Reply-To: <b1a84d36-4475-28e8-acde-5c18ebe94182@example.com>
  357. Some other Text"
  358. ticket_p6, article_6, user_6, mail = Channel::EmailParser.new.process({}, email_raw_string)
  359. ticket6 = Ticket.find(ticket_p6.id)
  360. assert_equal(ticket5.id, ticket6.id)
  361. assert_equal(subject, ticket6.title)
  362. end
  363. test 'process with follow up check - with none ticket# in subject' do
  364. Setting.set('postmaster_follow_up_search_in', [])
  365. Setting.set('ticket_hook_position', 'none')
  366. subject = 'some title'
  367. email_raw_string = "From: me@example.com
  368. To: bob@example.com
  369. Subject: #{subject}
  370. Message-ID: <123456789-follow-up-test-ticket_hook_position-none@linuxhotel.de>
  371. Some Text"
  372. ticket_p1, article_1, user_1, mail = Channel::EmailParser.new.process({}, email_raw_string)
  373. ticket1 = Ticket.find(ticket_p1.id)
  374. assert_equal(subject, ticket1.title)
  375. # follow up possible because same subject
  376. subject = 'new subject lalala'
  377. email_raw_string = "From: bob@example.com
  378. To: me@example.com
  379. Subject: AW: #{subject}
  380. Message-ID: <123456789-follow-up-test-ticket_hook_position-none-2@linuxhotel.de>
  381. References: <123456789-follow-up-test-ticket_hook_position-none@linuxhotel.de>
  382. Some Text"
  383. ticket_p2, article_p2, user_p2, mail = Channel::EmailParser.new.process({}, email_raw_string)
  384. ticket2 = Ticket.find(ticket_p2.id)
  385. assert_equal(ticket1.id, ticket2.id)
  386. end
  387. test 'process with follow up check - in body' do
  388. Setting.set('postmaster_follow_up_search_in', %w[body attachment references])
  389. Setting.set('ticket_hook', '#')
  390. email_raw_string = "From: me@example.com
  391. To: bob@example.com
  392. Subject: some subject
  393. Some Text"
  394. ticket_p1, article_1, user_1, mail = Channel::EmailParser.new.process({}, email_raw_string)
  395. email_raw_string = "From: me@example.com
  396. To: bob@example.com
  397. Subject: some subject
  398. Some Text #{Setting.get('ticket_hook')}#{ticket_p1.number} asdasd"
  399. ticket_p2, article_2, user_2, mail = Channel::EmailParser.new.process({}, email_raw_string)
  400. assert_equal(ticket_p1.id, ticket_p2.id)
  401. email_raw_string = "From: me@example.com
  402. To: bob@example.com
  403. Subject: some subject
  404. Content-Transfer-Encoding: 7bit
  405. Content-Type: text/html;
  406. <b>Some Text #{Setting.get('ticket_hook')}#{ticket_p1.number}</b>
  407. "
  408. ticket_p3, article_3, user_3, mail = Channel::EmailParser.new.process({}, email_raw_string)
  409. assert_equal(ticket_p1.id, ticket_p3.id)
  410. email_raw_string = "From: me@example.com
  411. To: bob@example.com
  412. Subject: some subject
  413. Content-Transfer-Encoding: 8bit
  414. Content-Type: text/html;
  415. <b>Some Text <span color=\"#{Setting.get('ticket_hook')}#{ticket_p1.number}\">test</span></b>
  416. "
  417. ticket_p4, article_4, user_4, mail = Channel::EmailParser.new.process({}, email_raw_string)
  418. assert_not_equal(ticket_p1.id, ticket_p4.id)
  419. end
  420. end