email_helper_test.rb 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. # Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
  2. require 'test_helper'
  3. class EmailHelperTest < ActiveSupport::TestCase
  4. test 'a mx_records' do
  5. domain = 'zammad.com'
  6. mx_domains = EmailHelper.mx_records(domain)
  7. assert_equal('mx2.zammad.com', mx_domains[0])
  8. end
  9. test 'a email parser test' do
  10. user, domain = EmailHelper.parse_email('somebody@example.com')
  11. assert_equal('somebody', user)
  12. assert_equal('example.com', domain)
  13. user, domain = EmailHelper.parse_email('somebody+test@example.com')
  14. assert_equal('somebody+test', user)
  15. assert_equal('example.com', domain)
  16. user, domain = EmailHelper.parse_email('somebody+testexample.com')
  17. assert_not(user)
  18. assert_not(domain)
  19. end
  20. test 'provider test' do
  21. email = 'linus@kernel.org'
  22. password = 'some_pw'
  23. map = EmailHelper.provider(email, password)
  24. assert_equal('imap', map[:google_imap][:inbound][:adapter])
  25. assert_equal('imap.gmail.com', map[:google_imap][:inbound][:options][:host])
  26. assert_equal(993, map[:google_imap][:inbound][:options][:port])
  27. assert_equal(email, map[:google_imap][:inbound][:options][:user])
  28. assert_equal(password, map[:google_imap][:inbound][:options][:password])
  29. assert_equal('smtp', map[:google_imap][:outbound][:adapter])
  30. assert_equal('smtp.gmail.com', map[:google_imap][:outbound][:options][:host])
  31. assert_equal(587, map[:google_imap][:outbound][:options][:port])
  32. assert_equal(true, map[:google_imap][:outbound][:options][:start_tls])
  33. assert_equal(email, map[:google_imap][:outbound][:options][:user])
  34. assert_equal(password, map[:google_imap][:outbound][:options][:password])
  35. end
  36. test 'provider_inbound_mx' do
  37. email = 'linus@zammad.com'
  38. password = 'some_pw'
  39. user, domain = EmailHelper.parse_email(email)
  40. mx_domains = EmailHelper.mx_records(domain)
  41. map = EmailHelper.provider_inbound_mx(user, email, password, mx_domains)
  42. assert_equal('imap', map[0][:adapter])
  43. assert_equal('mx2.zammad.com', map[0][:options][:host])
  44. assert_equal(993, map[0][:options][:port])
  45. assert_equal(user, map[0][:options][:user])
  46. assert_equal(password, map[0][:options][:password])
  47. assert_equal('imap', map[1][:adapter])
  48. assert_equal('mx2.zammad.com', map[1][:options][:host])
  49. assert_equal(993, map[1][:options][:port])
  50. assert_equal(email, map[1][:options][:user])
  51. assert_equal(password, map[1][:options][:password])
  52. end
  53. test 'provider_inbound_guess' do
  54. email = 'linus@zammad.com'
  55. password = 'some_pw'
  56. user, domain = EmailHelper.parse_email(email)
  57. map = EmailHelper.provider_inbound_guess(user, email, password, domain)
  58. assert_equal('imap', map[0][:adapter])
  59. assert_equal('mail.zammad.com', map[0][:options][:host])
  60. assert_equal(993, map[0][:options][:port])
  61. assert_equal(user, map[0][:options][:user])
  62. assert_equal(password, map[0][:options][:password])
  63. assert_equal('imap', map[1][:adapter])
  64. assert_equal('mail.zammad.com', map[1][:options][:host])
  65. assert_equal(993, map[1][:options][:port])
  66. assert_equal(email, map[1][:options][:user])
  67. assert_equal(password, map[1][:options][:password])
  68. assert_equal('imap', map[2][:adapter])
  69. assert_equal('imap.zammad.com', map[2][:options][:host])
  70. assert_equal(993, map[2][:options][:port])
  71. assert_equal(user, map[2][:options][:user])
  72. assert_equal(password, map[2][:options][:password])
  73. assert_equal('imap', map[3][:adapter])
  74. assert_equal('imap.zammad.com', map[3][:options][:host])
  75. assert_equal(993, map[3][:options][:port])
  76. assert_equal(email, map[3][:options][:user])
  77. assert_equal(password, map[3][:options][:password])
  78. end
  79. test 'provider_outbound_mx' do
  80. email = 'linus@zammad.com'
  81. password = 'some_pw'
  82. user, domain = EmailHelper.parse_email(email)
  83. mx_domains = EmailHelper.mx_records(domain)
  84. map = EmailHelper.provider_outbound_mx(user, email, password, mx_domains)
  85. assert_equal('smtp', map[0][:adapter])
  86. assert_equal('mx2.zammad.com', map[0][:options][:host])
  87. assert_equal(465, map[0][:options][:port])
  88. assert_equal(true, map[0][:options][:start_tls])
  89. assert_equal(user, map[0][:options][:user])
  90. assert_equal(password, map[0][:options][:password])
  91. assert_equal('smtp', map[1][:adapter])
  92. assert_equal('mx2.zammad.com', map[1][:options][:host])
  93. assert_equal(465, map[1][:options][:port])
  94. assert_equal(true, map[1][:options][:start_tls])
  95. assert_equal(email, map[1][:options][:user])
  96. assert_equal(password, map[1][:options][:password])
  97. assert_equal('smtp', map[2][:adapter])
  98. assert_equal('mx2.zammad.com', map[2][:options][:host])
  99. assert_equal(587, map[2][:options][:port])
  100. assert_nil(map[2][:options][:start_tls])
  101. assert_equal(user, map[2][:options][:user])
  102. assert_equal(password, map[2][:options][:password])
  103. assert_equal('smtp', map[3][:adapter])
  104. assert_equal('mx2.zammad.com', map[3][:options][:host])
  105. assert_equal(587, map[3][:options][:port])
  106. assert_nil(map[3][:options][:start_tls])
  107. assert_equal(email, map[3][:options][:user])
  108. assert_equal(password, map[3][:options][:password])
  109. end
  110. test 'provider_outbound_guess' do
  111. email = 'linus@zammad.com'
  112. password = 'some_pw'
  113. user, domain = EmailHelper.parse_email(email)
  114. map = EmailHelper.provider_outbound_guess(user, email, password, domain)
  115. assert_equal('smtp', map[0][:adapter])
  116. assert_equal('mail.zammad.com', map[0][:options][:host])
  117. assert_equal(465, map[0][:options][:port])
  118. assert_equal(true, map[0][:options][:start_tls])
  119. assert_equal(user, map[0][:options][:user])
  120. assert_equal(password, map[0][:options][:password])
  121. assert_equal('smtp', map[1][:adapter])
  122. assert_equal('mail.zammad.com', map[1][:options][:host])
  123. assert_equal(465, map[1][:options][:port])
  124. assert_equal(true, map[1][:options][:start_tls])
  125. assert_equal(email, map[1][:options][:user])
  126. assert_equal(password, map[1][:options][:password])
  127. assert_equal('smtp', map[2][:adapter])
  128. assert_equal('smtp.zammad.com', map[2][:options][:host])
  129. assert_equal(465, map[2][:options][:port])
  130. assert_equal(true, map[2][:options][:start_tls])
  131. assert_equal(user, map[2][:options][:user])
  132. assert_equal(password, map[2][:options][:password])
  133. assert_equal('smtp', map[3][:adapter])
  134. assert_equal('smtp.zammad.com', map[3][:options][:host])
  135. assert_equal(465, map[3][:options][:port])
  136. assert_equal(true, map[3][:options][:start_tls])
  137. assert_equal(email, map[3][:options][:user])
  138. assert_equal(password, map[3][:options][:password])
  139. end
  140. test 'z probe_inbound' do
  141. # invalid adapter
  142. result = EmailHelper::Probe.inbound(
  143. adapter: 'imap2',
  144. options: {
  145. host: 'nonexisting_host',
  146. port: 993,
  147. ssl: true,
  148. user: 'some@example.com',
  149. password: 'password',
  150. }
  151. )
  152. assert_equal('failed', result[:result])
  153. # network issues
  154. result = EmailHelper::Probe.inbound(
  155. adapter: 'imap',
  156. options: {
  157. host: 'nonexisting_host',
  158. port: 993,
  159. ssl: true,
  160. user: 'some@example.com',
  161. password: 'password',
  162. }
  163. )
  164. assert_equal('invalid', result[:result])
  165. assert_equal('Hostname not found!', result[:message_human])
  166. assert_equal('nonexisting_host', result[:settings][:options][:host])
  167. # try to access imap on host with blocked port to force a "Connection refused!" error
  168. result = EmailHelper::Probe.inbound(
  169. adapter: 'imap',
  170. options: {
  171. host: '127.0.0.1',
  172. port: 8, # no service to be expected
  173. ssl: true,
  174. user: 'some@example.com',
  175. password: 'password',
  176. }
  177. )
  178. assert_equal('invalid', result[:result])
  179. assert_equal('Connection refused!', result[:message_human])
  180. assert_equal('127.0.0.1', result[:settings][:options][:host])
  181. result = EmailHelper::Probe.inbound(
  182. adapter: 'imap',
  183. options: {
  184. host: '172.42.42.42',
  185. port: 993,
  186. ssl: true,
  187. user: 'some@example.com',
  188. password: 'password',
  189. }
  190. )
  191. assert_equal('invalid', result[:result])
  192. assert_match(%r{Host not reachable|No route to host}, result[:message_human])
  193. assert_equal('172.42.42.42', result[:settings][:options][:host])
  194. # gmail
  195. result = EmailHelper::Probe.inbound(
  196. adapter: 'imap',
  197. options: {
  198. host: 'imap.gmail.com',
  199. port: 993,
  200. ssl: true,
  201. user: 'some@example.com',
  202. password: 'password',
  203. }
  204. )
  205. assert_equal('invalid', result[:result])
  206. assert_match(%r{Authentication failed, username incorrect|Authentication failed, invalid credentials}, result[:message_human])
  207. assert_equal('imap.gmail.com', result[:settings][:options][:host])
  208. result = EmailHelper::Probe.inbound(
  209. adapter: 'imap',
  210. options: {
  211. host: 'imap.gmail.com',
  212. port: 993,
  213. ssl: true,
  214. user: 'frank.tailor05@googlemail.com',
  215. password: 'password',
  216. }
  217. )
  218. assert_equal('invalid', result[:result])
  219. # if we have to many failed logins, we need to handle another error message
  220. if result[:message_human].present?
  221. assert_match(%r{Authentication failed, username incorrect|Authentication failed, invalid credentials}, result[:message_human])
  222. else
  223. assert_match(%r{Web login required}, result[:message])
  224. end
  225. assert_equal('imap.gmail.com', result[:settings][:options][:host])
  226. # dovecot
  227. result = EmailHelper::Probe.inbound(
  228. adapter: 'imap',
  229. options: {
  230. host: 'mx2.zammad.com',
  231. port: 993,
  232. ssl: true,
  233. user: 'some@example.com',
  234. password: 'password',
  235. }
  236. )
  237. assert_equal('invalid', result[:result])
  238. assert_equal('Authentication failed!', result[:message_human])
  239. assert_equal('mx2.zammad.com', result[:settings][:options][:host])
  240. # realtest - test I
  241. if !ENV['EMAILHELPER_MAILBOX_1']
  242. raise "Need EMAILHELPER_MAILBOX_1 as ENV variable like export EMAILHELPER_MAILBOX_1='unittestemailhelper01@zammad.com:somepass'"
  243. end
  244. mailbox_user = ENV['EMAILHELPER_MAILBOX_1'].split(':')[0]
  245. mailbox_password = ENV['EMAILHELPER_MAILBOX_1'].split(':')[1]
  246. result = EmailHelper::Probe.inbound(
  247. adapter: 'imap',
  248. options: {
  249. host: 'mx2.zammad.com',
  250. port: 993,
  251. ssl: true,
  252. user: mailbox_user,
  253. password: mailbox_password,
  254. }
  255. )
  256. assert_equal('ok', result[:result])
  257. end
  258. test 'z probe_outbound' do
  259. # invalid adapter
  260. result = EmailHelper::Probe.outbound(
  261. {
  262. adapter: 'smtp2',
  263. options: {
  264. host: 'nonexisting_host',
  265. port: 25,
  266. start_tls: true,
  267. user: 'some@example.com',
  268. password: 'password',
  269. },
  270. },
  271. 'some@example.com',
  272. )
  273. assert_equal('failed', result[:result])
  274. # network issues
  275. result = EmailHelper::Probe.outbound(
  276. {
  277. adapter: 'smtp',
  278. options: {
  279. host: 'nonexisting_host',
  280. port: 25,
  281. start_tls: true,
  282. user: 'some@example.com',
  283. password: 'password',
  284. }
  285. },
  286. 'some@example.com',
  287. )
  288. assert_equal('invalid', result[:result])
  289. assert_equal('Hostname not found!', result[:message_human])
  290. assert_equal('nonexisting_host', result[:settings][:options][:host])
  291. # try to access SMTP on host with blocked port to force a "Connection refused!" error
  292. result = EmailHelper::Probe.outbound(
  293. {
  294. adapter: 'smtp',
  295. options: {
  296. host: '127.0.0.1',
  297. port: 8, # no service to be expected
  298. start_tls: true,
  299. user: 'some@example.com',
  300. password: 'password',
  301. }
  302. },
  303. 'some@example.com',
  304. )
  305. assert_equal('invalid', result[:result])
  306. assert_equal('Connection refused!', result[:message_human])
  307. assert_equal('127.0.0.1', result[:settings][:options][:host])
  308. result = EmailHelper::Probe.outbound(
  309. {
  310. adapter: 'smtp',
  311. options: {
  312. host: '172.42.42.42',
  313. port: 25,
  314. start_tls: true,
  315. user: 'some@example.com',
  316. password: 'password',
  317. }
  318. },
  319. 'some@example.com',
  320. )
  321. assert_equal('invalid', result[:result])
  322. assert_match(%r{Host not reachable|No route to host}, result[:message_human])
  323. assert_equal('172.42.42.42', result[:settings][:options][:host])
  324. # gmail
  325. result = EmailHelper::Probe.outbound(
  326. {
  327. adapter: 'smtp',
  328. options: {
  329. host: 'smtp.gmail.com',
  330. port: 25,
  331. start_tls: true,
  332. user: 'some@example.com',
  333. password: 'password',
  334. }
  335. },
  336. 'some@example.com',
  337. )
  338. assert_equal('invalid', result[:result])
  339. assert_equal('Authentication failed!', result[:message_human])
  340. assert_equal('smtp.gmail.com', result[:settings][:options][:host])
  341. result = EmailHelper::Probe.outbound(
  342. {
  343. adapter: 'smtp',
  344. options: {
  345. host: 'smtp.gmail.com',
  346. port: 25,
  347. start_tls: true,
  348. user: 'frank.tailor05@googlemail.com',
  349. password: 'password',
  350. }
  351. },
  352. 'some@example.com',
  353. )
  354. assert_equal('invalid', result[:result])
  355. # if we have to many failed logins, we need to handle another error message
  356. if result[:message_human].present?
  357. assert_equal('Authentication failed!', result[:message_human])
  358. else
  359. assert_match(%r{Please log in with your web browser and then try again}, result[:message])
  360. end
  361. assert_equal('smtp.gmail.com', result[:settings][:options][:host])
  362. # dovecot
  363. result = EmailHelper::Probe.outbound(
  364. {
  365. adapter: 'smtp',
  366. options: {
  367. host: 'mx2.zammad.com',
  368. port: 587,
  369. user: 'some@example.com',
  370. password: 'password',
  371. }
  372. },
  373. 'some@example.com',
  374. )
  375. assert_equal('invalid', result[:result])
  376. assert_equal('Authentication failed!', result[:message_human])
  377. assert_equal('mx2.zammad.com', result[:settings][:options][:host])
  378. # realtest - test I
  379. if !ENV['EMAILHELPER_MAILBOX_1']
  380. raise "Need EMAILHELPER_MAILBOX_1 as ENV variable like export EMAILHELPER_MAILBOX_1='unittestemailhelper01@zammad.com:somepass'"
  381. end
  382. mailbox_user = ENV['EMAILHELPER_MAILBOX_1'].split(':')[0]
  383. mailbox_password = ENV['EMAILHELPER_MAILBOX_1'].split(':')[1]
  384. result = EmailHelper::Probe.outbound(
  385. {
  386. adapter: 'smtp',
  387. options: {
  388. host: 'mx2.zammad.com',
  389. port: 587,
  390. user: mailbox_user,
  391. password: mailbox_password,
  392. }
  393. },
  394. mailbox_user,
  395. )
  396. assert_equal('ok', result[:result])
  397. end
  398. test 'zz probe' do
  399. result = EmailHelper::Probe.full(
  400. email: 'invalid_format',
  401. password: 'somepass',
  402. )
  403. assert_equal('invalid', result[:result])
  404. assert_not(result[:setting])
  405. # realtest - test I, with imap
  406. if !ENV['EMAILHELPER_MAILBOX_1']
  407. raise "Need EMAILHELPER_MAILBOX_1 as ENV variable like export EMAILHELPER_MAILBOX_1='unittestemailhelper01@zammad.com:somepass'"
  408. end
  409. mailbox_user = ENV['EMAILHELPER_MAILBOX_1'].split(':')[0]
  410. mailbox_password = ENV['EMAILHELPER_MAILBOX_1'].split(':')[1]
  411. result = EmailHelper::Probe.full(
  412. email: mailbox_user,
  413. password: mailbox_password,
  414. )
  415. assert_equal('ok', result[:result])
  416. assert_equal('mx2.zammad.com', result[:setting][:inbound][:options][:host])
  417. assert_equal('mx2.zammad.com', result[:setting][:outbound][:options][:host])
  418. # realtest - test II, gmail with only pop3
  419. if !ENV['EMAILHELPER_MAILBOX_2']
  420. raise "Need EMAILHELPER_MAILBOX_2 as ENV variable like export EMAILHELPER_MAILBOX_2='hansb36621@gmail.com:somepass'"
  421. end
  422. mailbox_user = ENV['EMAILHELPER_MAILBOX_2'].split(':')[0]
  423. mailbox_password = ENV['EMAILHELPER_MAILBOX_2'].split(':')[1]
  424. result = EmailHelper::Probe.full(
  425. email: mailbox_user,
  426. password: mailbox_password,
  427. )
  428. assert_nil(result[:reason])
  429. assert_equal('ok', result[:result])
  430. assert_equal('pop.gmail.com', result[:setting][:inbound][:options][:host])
  431. assert_equal('smtp.gmail.com', result[:setting][:outbound][:options][:host])
  432. end
  433. test 'zz verify' do
  434. # realtest - test I, with imap
  435. if !ENV['EMAILHELPER_MAILBOX_1']
  436. raise "Need EMAILHELPER_MAILBOX_1 as ENV variable like export EMAILHELPER_MAILBOX_1='unittestemailhelper01@zammad.com:somepass'"
  437. end
  438. mailbox_user = ENV['EMAILHELPER_MAILBOX_1'].split(':')[0]
  439. mailbox_password = ENV['EMAILHELPER_MAILBOX_1'].split(':')[1]
  440. result = EmailHelper::Verify.email(
  441. inbound: {
  442. adapter: 'imap',
  443. options: {
  444. host: 'mx2.zammad.com',
  445. port: 993,
  446. ssl: true,
  447. user: mailbox_user,
  448. password: mailbox_password,
  449. },
  450. },
  451. outbound: {
  452. adapter: 'smtp',
  453. options: {
  454. host: 'mx2.zammad.com',
  455. port: 587,
  456. user: mailbox_user,
  457. password: mailbox_password,
  458. },
  459. },
  460. sender: mailbox_user,
  461. )
  462. assert_equal('ok', result[:result])
  463. # realtest - test II, gmail with pop3
  464. if !ENV['EMAILHELPER_MAILBOX_2']
  465. raise "Need EMAILHELPER_MAILBOX_2 as ENV variable like export EMAILHELPER_MAILBOX_2='hansb36621@gmail.com:somepass'"
  466. end
  467. mailbox_user = ENV['EMAILHELPER_MAILBOX_2'].split(':')[0]
  468. mailbox_password = ENV['EMAILHELPER_MAILBOX_2'].split(':')[1]
  469. EmailHelper.parse_email(mailbox_user)
  470. result = EmailHelper::Verify.email(
  471. inbound: {
  472. adapter: 'pop3',
  473. options: {
  474. host: 'pop.gmail.com',
  475. port: 995,
  476. ssl: true,
  477. user: mailbox_user,
  478. password: mailbox_password,
  479. },
  480. },
  481. outbound: {
  482. adapter: 'smtp',
  483. options: {
  484. host: 'smtp.gmail.com',
  485. port: 587,
  486. start_tls: true,
  487. user: mailbox_user,
  488. password: mailbox_password,
  489. },
  490. },
  491. sender: mailbox_user,
  492. )
  493. assert_equal('ok', result[:result])
  494. end
  495. end