email_process_follow_up_test.rb 18 KB

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