sisimai 4.14.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sisimai might be problematic. Click here for more details.

Files changed (562) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +165 -0
  5. data/.travis.yml +21 -0
  6. data/ANALYTICAL-PRECISION +54 -0
  7. data/Changes +5 -0
  8. data/Developers.mk +129 -0
  9. data/Gemfile +9 -0
  10. data/LICENSE +26 -0
  11. data/Makefile +56 -0
  12. data/README.md +300 -0
  13. data/Rakefile +7 -0
  14. data/Repository.mk +69 -0
  15. data/bin/console +14 -0
  16. data/bin/setup +7 -0
  17. data/lib/sisimai.rb +60 -0
  18. data/lib/sisimai/address.rb +218 -0
  19. data/lib/sisimai/arf.rb +343 -0
  20. data/lib/sisimai/data.rb +413 -0
  21. data/lib/sisimai/data/json.rb +36 -0
  22. data/lib/sisimai/data/yaml.rb +32 -0
  23. data/lib/sisimai/datetime.rb +518 -0
  24. data/lib/sisimai/mail.rb +82 -0
  25. data/lib/sisimai/mail/maildir.rb +85 -0
  26. data/lib/sisimai/mail/mbox.rb +69 -0
  27. data/lib/sisimai/mail/stdin.rb +52 -0
  28. data/lib/sisimai/mda.rb +152 -0
  29. data/lib/sisimai/message.rb +510 -0
  30. data/lib/sisimai/mime.rb +127 -0
  31. data/lib/sisimai/msp.rb +54 -0
  32. data/lib/sisimai/msp/de/einsundeins.rb +174 -0
  33. data/lib/sisimai/msp/de/gmx.rb +197 -0
  34. data/lib/sisimai/msp/jp/biglobe.rb +179 -0
  35. data/lib/sisimai/msp/jp/ezweb.rb +292 -0
  36. data/lib/sisimai/msp/jp/kddi.rb +195 -0
  37. data/lib/sisimai/msp/ru/mailru.rb +306 -0
  38. data/lib/sisimai/msp/ru/yandex.rb +241 -0
  39. data/lib/sisimai/msp/uk/messagelabs.rb +250 -0
  40. data/lib/sisimai/msp/us/amazonses.rb +248 -0
  41. data/lib/sisimai/msp/us/aol.rb +234 -0
  42. data/lib/sisimai/msp/us/bigfoot.rb +243 -0
  43. data/lib/sisimai/msp/us/facebook.rb +306 -0
  44. data/lib/sisimai/msp/us/google.rb +357 -0
  45. data/lib/sisimai/msp/us/outlook.rb +243 -0
  46. data/lib/sisimai/msp/us/receivingses.rb +247 -0
  47. data/lib/sisimai/msp/us/sendgrid.rb +257 -0
  48. data/lib/sisimai/msp/us/verizon.rb +311 -0
  49. data/lib/sisimai/msp/us/yahoo.rb +178 -0
  50. data/lib/sisimai/msp/us/zoho.rb +198 -0
  51. data/lib/sisimai/mta.rb +55 -0
  52. data/lib/sisimai/mta/activehunter.rb +155 -0
  53. data/lib/sisimai/mta/apachejames.rb +194 -0
  54. data/lib/sisimai/mta/courier.rb +307 -0
  55. data/lib/sisimai/mta/domino.rb +209 -0
  56. data/lib/sisimai/mta/exchange.rb +314 -0
  57. data/lib/sisimai/mta/exim.rb +549 -0
  58. data/lib/sisimai/mta/imailserver.rb +227 -0
  59. data/lib/sisimai/mta/interscanmss.rb +167 -0
  60. data/lib/sisimai/mta/mailfoundry.rb +173 -0
  61. data/lib/sisimai/mta/mailmarshalsmtp.rb +206 -0
  62. data/lib/sisimai/mta/mcafee.rb +201 -0
  63. data/lib/sisimai/mta/messagingserver.rb +241 -0
  64. data/lib/sisimai/mta/mfilter.rb +190 -0
  65. data/lib/sisimai/mta/mxlogic.rb +283 -0
  66. data/lib/sisimai/mta/notes.rb +206 -0
  67. data/lib/sisimai/mta/opensmtpd.rb +225 -0
  68. data/lib/sisimai/mta/postfix.rb +306 -0
  69. data/lib/sisimai/mta/qmail.rb +335 -0
  70. data/lib/sisimai/mta/sendmail.rb +317 -0
  71. data/lib/sisimai/mta/surfcontrol.rb +193 -0
  72. data/lib/sisimai/mta/userdefined.rb +148 -0
  73. data/lib/sisimai/mta/v5sendmail.rb +232 -0
  74. data/lib/sisimai/mta/x1.rb +156 -0
  75. data/lib/sisimai/mta/x2.rb +157 -0
  76. data/lib/sisimai/mta/x3.rb +171 -0
  77. data/lib/sisimai/mta/x4.rb +365 -0
  78. data/lib/sisimai/mta/x5.rb +208 -0
  79. data/lib/sisimai/order.rb +217 -0
  80. data/lib/sisimai/reason.rb +235 -0
  81. data/lib/sisimai/reason/blocked.rb +105 -0
  82. data/lib/sisimai/reason/contenterror.rb +53 -0
  83. data/lib/sisimai/reason/exceedlimit.rb +60 -0
  84. data/lib/sisimai/reason/expired.rb +53 -0
  85. data/lib/sisimai/reason/filtered.rb +98 -0
  86. data/lib/sisimai/reason/hasmoved.rb +45 -0
  87. data/lib/sisimai/reason/hostunknown.rb +74 -0
  88. data/lib/sisimai/reason/mailboxfull.rb +118 -0
  89. data/lib/sisimai/reason/mailererror.rb +55 -0
  90. data/lib/sisimai/reason/mesgtoobig.rb +77 -0
  91. data/lib/sisimai/reason/networkerror.rb +57 -0
  92. data/lib/sisimai/reason/norelaying.rb +71 -0
  93. data/lib/sisimai/reason/notaccept.rb +63 -0
  94. data/lib/sisimai/reason/onhold.rb +45 -0
  95. data/lib/sisimai/reason/rejected.rb +101 -0
  96. data/lib/sisimai/reason/securityerror.rb +72 -0
  97. data/lib/sisimai/reason/spamdetected.rb +172 -0
  98. data/lib/sisimai/reason/suspend.rb +58 -0
  99. data/lib/sisimai/reason/systemerror.rb +69 -0
  100. data/lib/sisimai/reason/systemfull.rb +45 -0
  101. data/lib/sisimai/reason/toomanyconn.rb +73 -0
  102. data/lib/sisimai/reason/userunknown.rb +194 -0
  103. data/lib/sisimai/rfc2606.rb +24 -0
  104. data/lib/sisimai/rfc3464.rb +497 -0
  105. data/lib/sisimai/rfc3834.rb +150 -0
  106. data/lib/sisimai/rfc5322.rb +204 -0
  107. data/lib/sisimai/rhost.rb +47 -0
  108. data/lib/sisimai/rhost/googleapps.rb +237 -0
  109. data/lib/sisimai/smtp.rb +58 -0
  110. data/lib/sisimai/smtp/reply.rb +81 -0
  111. data/lib/sisimai/smtp/status.rb +755 -0
  112. data/lib/sisimai/string.rb +65 -0
  113. data/lib/sisimai/time.rb +11 -0
  114. data/lib/sisimai/version.rb +4 -0
  115. data/set-of-emails/README.md +35 -0
  116. data/set-of-emails/mailbox/mbox-0 +2467 -0
  117. data/set-of-emails/mailbox/mbox-1 +71 -0
  118. data/set-of-emails/maildir/bsd/README.md +261 -0
  119. data/set-of-emails/maildir/bsd/activehunter-01.eml +54 -0
  120. data/set-of-emails/maildir/bsd/activehunter-02.eml +53 -0
  121. data/set-of-emails/maildir/bsd/apachejames-01.eml +46 -0
  122. data/set-of-emails/maildir/bsd/arf-01.eml +66 -0
  123. data/set-of-emails/maildir/bsd/arf-02.eml +68 -0
  124. data/set-of-emails/maildir/bsd/arf-03.eml +56 -0
  125. data/set-of-emails/maildir/bsd/arf-04.eml +89 -0
  126. data/set-of-emails/maildir/bsd/arf-05.eml +82 -0
  127. data/set-of-emails/maildir/bsd/arf-06.eml +166 -0
  128. data/set-of-emails/maildir/bsd/arf-07.eml +59 -0
  129. data/set-of-emails/maildir/bsd/arf-08.eml +103 -0
  130. data/set-of-emails/maildir/bsd/arf-09.eml +104 -0
  131. data/set-of-emails/maildir/bsd/arf-10.eml +56 -0
  132. data/set-of-emails/maildir/bsd/arf-11.eml +37 -0
  133. data/set-of-emails/maildir/bsd/arf-12.eml +40 -0
  134. data/set-of-emails/maildir/bsd/arf-13.eml +76 -0
  135. data/set-of-emails/maildir/bsd/arf-14.eml +333 -0
  136. data/set-of-emails/maildir/bsd/arf-15.eml +66 -0
  137. data/set-of-emails/maildir/bsd/courier-01.eml +79 -0
  138. data/set-of-emails/maildir/bsd/courier-02.eml +83 -0
  139. data/set-of-emails/maildir/bsd/courier-03.eml +85 -0
  140. data/set-of-emails/maildir/bsd/courier-04.eml +87 -0
  141. data/set-of-emails/maildir/bsd/de-einsundeins-01.eml +38 -0
  142. data/set-of-emails/maildir/bsd/de-gmx-01.eml +52 -0
  143. data/set-of-emails/maildir/bsd/de-gmx-02.eml +51 -0
  144. data/set-of-emails/maildir/bsd/de-gmx-03.eml +56 -0
  145. data/set-of-emails/maildir/bsd/de-gmx-04.eml +51 -0
  146. data/set-of-emails/maildir/bsd/domino-01.eml +33 -0
  147. data/set-of-emails/maildir/bsd/domino-02.eml +83 -0
  148. data/set-of-emails/maildir/bsd/exchange-01.eml +31 -0
  149. data/set-of-emails/maildir/bsd/exchange-02.eml +67 -0
  150. data/set-of-emails/maildir/bsd/exchange-03.eml +52 -0
  151. data/set-of-emails/maildir/bsd/exchange-04.eml +28 -0
  152. data/set-of-emails/maildir/bsd/exchange-05.eml +56 -0
  153. data/set-of-emails/maildir/bsd/exchange-06.eml +151 -0
  154. data/set-of-emails/maildir/bsd/exim-01.eml +46 -0
  155. data/set-of-emails/maildir/bsd/exim-02.eml +41 -0
  156. data/set-of-emails/maildir/bsd/exim-03.eml +42 -0
  157. data/set-of-emails/maildir/bsd/exim-04.eml +46 -0
  158. data/set-of-emails/maildir/bsd/exim-05.eml +49 -0
  159. data/set-of-emails/maildir/bsd/exim-06.eml +44 -0
  160. data/set-of-emails/maildir/bsd/exim-07.eml +28 -0
  161. data/set-of-emails/maildir/bsd/exim-08.eml +42 -0
  162. data/set-of-emails/maildir/bsd/exim-09.eml +169 -0
  163. data/set-of-emails/maildir/bsd/exim-10.eml +718 -0
  164. data/set-of-emails/maildir/bsd/exim-11.eml +718 -0
  165. data/set-of-emails/maildir/bsd/exim-12.eml +75 -0
  166. data/set-of-emails/maildir/bsd/exim-13.eml +145 -0
  167. data/set-of-emails/maildir/bsd/exim-14.eml +32 -0
  168. data/set-of-emails/maildir/bsd/exim-15.eml +49 -0
  169. data/set-of-emails/maildir/bsd/exim-16.eml +98 -0
  170. data/set-of-emails/maildir/bsd/exim-17.eml +50 -0
  171. data/set-of-emails/maildir/bsd/exim-18.eml +96 -0
  172. data/set-of-emails/maildir/bsd/exim-19.eml +52 -0
  173. data/set-of-emails/maildir/bsd/exim-20.eml +159 -0
  174. data/set-of-emails/maildir/bsd/exim-21.eml +150 -0
  175. data/set-of-emails/maildir/bsd/exim-22.eml +50 -0
  176. data/set-of-emails/maildir/bsd/exim-23.eml +57 -0
  177. data/set-of-emails/maildir/bsd/exim-24.eml +107 -0
  178. data/set-of-emails/maildir/bsd/exim-25.eml +18 -0
  179. data/set-of-emails/maildir/bsd/exim-26.eml +111 -0
  180. data/set-of-emails/maildir/bsd/exim-27.eml +120 -0
  181. data/set-of-emails/maildir/bsd/exim-28.eml +148 -0
  182. data/set-of-emails/maildir/bsd/google-apps-01.eml +66 -0
  183. data/set-of-emails/maildir/bsd/imailserver-01.eml +27 -0
  184. data/set-of-emails/maildir/bsd/imailserver-02.eml +36 -0
  185. data/set-of-emails/maildir/bsd/imailserver-03.eml +28 -0
  186. data/set-of-emails/maildir/bsd/imailserver-04.eml +15 -0
  187. data/set-of-emails/maildir/bsd/imailserver-05.eml +92 -0
  188. data/set-of-emails/maildir/bsd/imailserver-06.eml +29 -0
  189. data/set-of-emails/maildir/bsd/interscanmss-01.eml +49 -0
  190. data/set-of-emails/maildir/bsd/interscanmss-02.eml +259 -0
  191. data/set-of-emails/maildir/bsd/jp-biglobe-01.eml +43 -0
  192. data/set-of-emails/maildir/bsd/jp-ezweb-01.eml +36 -0
  193. data/set-of-emails/maildir/bsd/jp-ezweb-02.eml +65 -0
  194. data/set-of-emails/maildir/bsd/jp-ezweb-03.eml +35 -0
  195. data/set-of-emails/maildir/bsd/jp-ezweb-04.eml +38 -0
  196. data/set-of-emails/maildir/bsd/jp-ezweb-05.eml +38 -0
  197. data/set-of-emails/maildir/bsd/jp-ezweb-06.eml +33 -0
  198. data/set-of-emails/maildir/bsd/jp-kddi-01.eml +49 -0
  199. data/set-of-emails/maildir/bsd/jp-kddi-02.eml +54 -0
  200. data/set-of-emails/maildir/bsd/jp-kddi-03.eml +54 -0
  201. data/set-of-emails/maildir/bsd/mailfoundry-01.eml +50 -0
  202. data/set-of-emails/maildir/bsd/mailfoundry-02.eml +49 -0
  203. data/set-of-emails/maildir/bsd/mailmarshalsmtp-01.eml +43 -0
  204. data/set-of-emails/maildir/bsd/mcafee-01.eml +63 -0
  205. data/set-of-emails/maildir/bsd/mcafee-02.eml +65 -0
  206. data/set-of-emails/maildir/bsd/mcafee-03.eml +59 -0
  207. data/set-of-emails/maildir/bsd/messagingserver-01.eml +102 -0
  208. data/set-of-emails/maildir/bsd/messagingserver-02.eml +72 -0
  209. data/set-of-emails/maildir/bsd/messagingserver-03.eml +70 -0
  210. data/set-of-emails/maildir/bsd/messagingserver-04.eml +102 -0
  211. data/set-of-emails/maildir/bsd/messagingserver-05.eml +98 -0
  212. data/set-of-emails/maildir/bsd/messagingserver-06.eml +101 -0
  213. data/set-of-emails/maildir/bsd/messagingserver-07.eml +129 -0
  214. data/set-of-emails/maildir/bsd/mfilter-01.eml +49 -0
  215. data/set-of-emails/maildir/bsd/mfilter-02.eml +48 -0
  216. data/set-of-emails/maildir/bsd/mfilter-03.eml +43 -0
  217. data/set-of-emails/maildir/bsd/mxlogic-01.eml +47 -0
  218. data/set-of-emails/maildir/bsd/mxlogic-02.eml +44 -0
  219. data/set-of-emails/maildir/bsd/mxlogic-03.eml +46 -0
  220. data/set-of-emails/maildir/bsd/notes-01.eml +42 -0
  221. data/set-of-emails/maildir/bsd/notes-02.eml +42 -0
  222. data/set-of-emails/maildir/bsd/notes-03.eml +38 -0
  223. data/set-of-emails/maildir/bsd/notes-04.eml +181 -0
  224. data/set-of-emails/maildir/bsd/opensmtpd-01.eml +33 -0
  225. data/set-of-emails/maildir/bsd/opensmtpd-02.eml +33 -0
  226. data/set-of-emails/maildir/bsd/opensmtpd-03.eml +36 -0
  227. data/set-of-emails/maildir/bsd/opensmtpd-04.eml +40 -0
  228. data/set-of-emails/maildir/bsd/opensmtpd-05.eml +36 -0
  229. data/set-of-emails/maildir/bsd/postfix-01.eml +60 -0
  230. data/set-of-emails/maildir/bsd/postfix-02.eml +78 -0
  231. data/set-of-emails/maildir/bsd/postfix-03.eml +71 -0
  232. data/set-of-emails/maildir/bsd/postfix-04.eml +89 -0
  233. data/set-of-emails/maildir/bsd/postfix-05.eml +78 -0
  234. data/set-of-emails/maildir/bsd/postfix-06.eml +72 -0
  235. data/set-of-emails/maildir/bsd/postfix-07.eml +74 -0
  236. data/set-of-emails/maildir/bsd/postfix-08.eml +78 -0
  237. data/set-of-emails/maildir/bsd/postfix-09.eml +76 -0
  238. data/set-of-emails/maildir/bsd/postfix-10.eml +73 -0
  239. data/set-of-emails/maildir/bsd/postfix-11.eml +86 -0
  240. data/set-of-emails/maildir/bsd/postfix-12.eml +71 -0
  241. data/set-of-emails/maildir/bsd/postfix-13.eml +81 -0
  242. data/set-of-emails/maildir/bsd/postfix-14.eml +68 -0
  243. data/set-of-emails/maildir/bsd/postfix-15.eml +69 -0
  244. data/set-of-emails/maildir/bsd/postfix-16.eml +73 -0
  245. data/set-of-emails/maildir/bsd/postfix-17.eml +68 -0
  246. data/set-of-emails/maildir/bsd/postfix-18.eml +121 -0
  247. data/set-of-emails/maildir/bsd/postfix-19.eml +105 -0
  248. data/set-of-emails/maildir/bsd/postfix-20.eml +231 -0
  249. data/set-of-emails/maildir/bsd/postfix-21.eml +60 -0
  250. data/set-of-emails/maildir/bsd/qmail-01.eml +40 -0
  251. data/set-of-emails/maildir/bsd/qmail-02.eml +35 -0
  252. data/set-of-emails/maildir/bsd/qmail-03.eml +22 -0
  253. data/set-of-emails/maildir/bsd/qmail-04.eml +31 -0
  254. data/set-of-emails/maildir/bsd/qmail-05.eml +31 -0
  255. data/set-of-emails/maildir/bsd/qmail-06.eml +39 -0
  256. data/set-of-emails/maildir/bsd/qmail-07.eml +22 -0
  257. data/set-of-emails/maildir/bsd/qmail-08.eml +23 -0
  258. data/set-of-emails/maildir/bsd/qmail-09.eml +103 -0
  259. data/set-of-emails/maildir/bsd/rfc3464-01.eml +60 -0
  260. data/set-of-emails/maildir/bsd/rfc3464-02.eml +43 -0
  261. data/set-of-emails/maildir/bsd/rfc3464-03.eml +40 -0
  262. data/set-of-emails/maildir/bsd/rfc3464-04.eml +50 -0
  263. data/set-of-emails/maildir/bsd/rfc3464-05.eml +63 -0
  264. data/set-of-emails/maildir/bsd/rfc3464-06.eml +48 -0
  265. data/set-of-emails/maildir/bsd/rfc3464-07.eml +88 -0
  266. data/set-of-emails/maildir/bsd/rfc3464-08.eml +70 -0
  267. data/set-of-emails/maildir/bsd/rfc3464-09.eml +93 -0
  268. data/set-of-emails/maildir/bsd/rfc3464-10.eml +467 -0
  269. data/set-of-emails/maildir/bsd/rfc3464-11.eml +1171 -0
  270. data/set-of-emails/maildir/bsd/rfc3464-12.eml +101 -0
  271. data/set-of-emails/maildir/bsd/rfc3464-13.eml +131 -0
  272. data/set-of-emails/maildir/bsd/rfc3464-14.eml +121 -0
  273. data/set-of-emails/maildir/bsd/rfc3464-15.eml +144 -0
  274. data/set-of-emails/maildir/bsd/rfc3464-16.eml +36 -0
  275. data/set-of-emails/maildir/bsd/rfc3464-17.eml +109 -0
  276. data/set-of-emails/maildir/bsd/rfc3464-18.eml +149 -0
  277. data/set-of-emails/maildir/bsd/rfc3464-19.eml +65 -0
  278. data/set-of-emails/maildir/bsd/rfc3464-20.eml +145 -0
  279. data/set-of-emails/maildir/bsd/rfc3464-21.eml +146 -0
  280. data/set-of-emails/maildir/bsd/rfc3464-22.eml +105 -0
  281. data/set-of-emails/maildir/bsd/rfc3464-23.eml +21 -0
  282. data/set-of-emails/maildir/bsd/rfc3464-24.eml +27 -0
  283. data/set-of-emails/maildir/bsd/rfc3464-25.eml +33 -0
  284. data/set-of-emails/maildir/bsd/rfc3464-26.eml +98 -0
  285. data/set-of-emails/maildir/bsd/rfc3464-27.eml +180 -0
  286. data/set-of-emails/maildir/bsd/rfc3834-01.eml +37 -0
  287. data/set-of-emails/maildir/bsd/rfc3834-02.eml +51 -0
  288. data/set-of-emails/maildir/bsd/rfc3834-03.eml +33 -0
  289. data/set-of-emails/maildir/bsd/ru-mailru-01.eml +54 -0
  290. data/set-of-emails/maildir/bsd/ru-mailru-02.eml +54 -0
  291. data/set-of-emails/maildir/bsd/ru-mailru-03.eml +62 -0
  292. data/set-of-emails/maildir/bsd/ru-mailru-04.eml +54 -0
  293. data/set-of-emails/maildir/bsd/ru-yandex-01.eml +102 -0
  294. data/set-of-emails/maildir/bsd/ru-yandex-02.eml +113 -0
  295. data/set-of-emails/maildir/bsd/ru-yandex-03.eml +101 -0
  296. data/set-of-emails/maildir/bsd/sendmail-01.eml +70 -0
  297. data/set-of-emails/maildir/bsd/sendmail-02.eml +82 -0
  298. data/set-of-emails/maildir/bsd/sendmail-03.eml +76 -0
  299. data/set-of-emails/maildir/bsd/sendmail-04.eml +63 -0
  300. data/set-of-emails/maildir/bsd/sendmail-05.eml +64 -0
  301. data/set-of-emails/maildir/bsd/sendmail-06.eml +67 -0
  302. data/set-of-emails/maildir/bsd/sendmail-07.eml +65 -0
  303. data/set-of-emails/maildir/bsd/sendmail-08.eml +62 -0
  304. data/set-of-emails/maildir/bsd/sendmail-09.eml +60 -0
  305. data/set-of-emails/maildir/bsd/sendmail-10.eml +82 -0
  306. data/set-of-emails/maildir/bsd/sendmail-11.eml +60 -0
  307. data/set-of-emails/maildir/bsd/sendmail-12.eml +62 -0
  308. data/set-of-emails/maildir/bsd/sendmail-13.eml +66 -0
  309. data/set-of-emails/maildir/bsd/sendmail-14.eml +64 -0
  310. data/set-of-emails/maildir/bsd/sendmail-15.eml +60 -0
  311. data/set-of-emails/maildir/bsd/sendmail-16.eml +69 -0
  312. data/set-of-emails/maildir/bsd/sendmail-17.eml +68 -0
  313. data/set-of-emails/maildir/bsd/sendmail-18.eml +64 -0
  314. data/set-of-emails/maildir/bsd/sendmail-19.eml +71 -0
  315. data/set-of-emails/maildir/bsd/sendmail-20.eml +120 -0
  316. data/set-of-emails/maildir/bsd/sendmail-21.eml +69 -0
  317. data/set-of-emails/maildir/bsd/sendmail-22.eml +73 -0
  318. data/set-of-emails/maildir/bsd/sendmail-23.eml +137 -0
  319. data/set-of-emails/maildir/bsd/sendmail-24.eml +66 -0
  320. data/set-of-emails/maildir/bsd/sendmail-25.eml +70 -0
  321. data/set-of-emails/maildir/bsd/sendmail-26.eml +71 -0
  322. data/set-of-emails/maildir/bsd/sendmail-27.eml +69 -0
  323. data/set-of-emails/maildir/bsd/sendmail-28.eml +69 -0
  324. data/set-of-emails/maildir/bsd/sendmail-29.eml +70 -0
  325. data/set-of-emails/maildir/bsd/sendmail-30.eml +68 -0
  326. data/set-of-emails/maildir/bsd/sendmail-31.eml +80 -0
  327. data/set-of-emails/maildir/bsd/sendmail-32.eml +71 -0
  328. data/set-of-emails/maildir/bsd/sendmail-33.eml +71 -0
  329. data/set-of-emails/maildir/bsd/sendmail-34.eml +75 -0
  330. data/set-of-emails/maildir/bsd/sendmail-35.eml +70 -0
  331. data/set-of-emails/maildir/bsd/sendmail-36.eml +71 -0
  332. data/set-of-emails/maildir/bsd/sendmail-37.eml +71 -0
  333. data/set-of-emails/maildir/bsd/surfcontrol-01.eml +79 -0
  334. data/set-of-emails/maildir/bsd/surfcontrol-02.eml +70 -0
  335. data/set-of-emails/maildir/bsd/surfcontrol-03.eml +70 -0
  336. data/set-of-emails/maildir/bsd/uk-messagelabs-01.eml +76 -0
  337. data/set-of-emails/maildir/bsd/us-amazonses-01.eml +59 -0
  338. data/set-of-emails/maildir/bsd/us-amazonses-02.eml +177 -0
  339. data/set-of-emails/maildir/bsd/us-amazonses-03.eml +55 -0
  340. data/set-of-emails/maildir/bsd/us-amazonses-04.eml +55 -0
  341. data/set-of-emails/maildir/bsd/us-aol-01.eml +1258 -0
  342. data/set-of-emails/maildir/bsd/us-aol-02.eml +1257 -0
  343. data/set-of-emails/maildir/bsd/us-aol-03.eml +1264 -0
  344. data/set-of-emails/maildir/bsd/us-aol-04.eml +1260 -0
  345. data/set-of-emails/maildir/bsd/us-bigfoot-01.eml +64 -0
  346. data/set-of-emails/maildir/bsd/us-facebook-01.eml +40 -0
  347. data/set-of-emails/maildir/bsd/us-facebook-02.eml +42 -0
  348. data/set-of-emails/maildir/bsd/us-google-01.eml +70 -0
  349. data/set-of-emails/maildir/bsd/us-google-02.eml +50 -0
  350. data/set-of-emails/maildir/bsd/us-google-03.eml +51 -0
  351. data/set-of-emails/maildir/bsd/us-google-04.eml +82 -0
  352. data/set-of-emails/maildir/bsd/us-google-05.eml +50 -0
  353. data/set-of-emails/maildir/bsd/us-google-06.eml +56 -0
  354. data/set-of-emails/maildir/bsd/us-google-07.eml +42 -0
  355. data/set-of-emails/maildir/bsd/us-google-08.eml +59 -0
  356. data/set-of-emails/maildir/bsd/us-google-09.eml +76 -0
  357. data/set-of-emails/maildir/bsd/us-google-10.eml +69 -0
  358. data/set-of-emails/maildir/bsd/us-google-11.eml +68 -0
  359. data/set-of-emails/maildir/bsd/us-google-12.eml +76 -0
  360. data/set-of-emails/maildir/bsd/us-google-13.eml +79 -0
  361. data/set-of-emails/maildir/bsd/us-google-14.eml +304 -0
  362. data/set-of-emails/maildir/bsd/us-outlook-01.eml +72 -0
  363. data/set-of-emails/maildir/bsd/us-outlook-02.eml +72 -0
  364. data/set-of-emails/maildir/bsd/us-outlook-03.eml +72 -0
  365. data/set-of-emails/maildir/bsd/us-outlook-04.eml +79 -0
  366. data/set-of-emails/maildir/bsd/us-outlook-05.eml +85 -0
  367. data/set-of-emails/maildir/bsd/us-outlook-06.eml +75 -0
  368. data/set-of-emails/maildir/bsd/us-outlook-07.eml +70 -0
  369. data/set-of-emails/maildir/bsd/us-receivingses-01.eml +74 -0
  370. data/set-of-emails/maildir/bsd/us-receivingses-02.eml +74 -0
  371. data/set-of-emails/maildir/bsd/us-receivingses-03.eml +74 -0
  372. data/set-of-emails/maildir/bsd/us-receivingses-04.eml +74 -0
  373. data/set-of-emails/maildir/bsd/us-receivingses-05.eml +74 -0
  374. data/set-of-emails/maildir/bsd/us-receivingses-06.eml +74 -0
  375. data/set-of-emails/maildir/bsd/us-receivingses-07.eml +74 -0
  376. data/set-of-emails/maildir/bsd/us-sendgrid-01.eml +95 -0
  377. data/set-of-emails/maildir/bsd/us-sendgrid-02.eml +98 -0
  378. data/set-of-emails/maildir/bsd/us-sendgrid-03.eml +100 -0
  379. data/set-of-emails/maildir/bsd/us-verizon-01.eml +31 -0
  380. data/set-of-emails/maildir/bsd/us-yahoo-01.eml +78 -0
  381. data/set-of-emails/maildir/bsd/us-yahoo-02.eml +79 -0
  382. data/set-of-emails/maildir/bsd/us-yahoo-03.eml +93 -0
  383. data/set-of-emails/maildir/bsd/us-yahoo-04.eml +94 -0
  384. data/set-of-emails/maildir/bsd/us-yahoo-05.eml +94 -0
  385. data/set-of-emails/maildir/bsd/us-zoho-01.eml +40 -0
  386. data/set-of-emails/maildir/bsd/us-zoho-02.eml +38 -0
  387. data/set-of-emails/maildir/bsd/us-zoho-03.eml +37 -0
  388. data/set-of-emails/maildir/bsd/us-zoho-04.eml +47 -0
  389. data/set-of-emails/maildir/bsd/us-zoho-05.eml +37 -0
  390. data/set-of-emails/maildir/bsd/v5sendmail-01.eml +24 -0
  391. data/set-of-emails/maildir/bsd/v5sendmail-02.eml +26 -0
  392. data/set-of-emails/maildir/bsd/v5sendmail-03.eml +29 -0
  393. data/set-of-emails/maildir/bsd/v5sendmail-04.eml +29 -0
  394. data/set-of-emails/maildir/bsd/v5sendmail-05.eml +42 -0
  395. data/set-of-emails/maildir/bsd/v5sendmail-06.eml +28 -0
  396. data/set-of-emails/maildir/bsd/v5sendmail-07.eml +35 -0
  397. data/set-of-emails/maildir/bsd/x1-01.eml +61 -0
  398. data/set-of-emails/maildir/bsd/x1-02.eml +62 -0
  399. data/set-of-emails/maildir/bsd/x2-01.eml +41 -0
  400. data/set-of-emails/maildir/bsd/x2-02.eml +46 -0
  401. data/set-of-emails/maildir/bsd/x2-03.eml +34 -0
  402. data/set-of-emails/maildir/bsd/x2-04.eml +0 -0
  403. data/set-of-emails/maildir/bsd/x2-05.eml +98 -0
  404. data/set-of-emails/maildir/bsd/x3-01.eml +61 -0
  405. data/set-of-emails/maildir/bsd/x3-02.eml +64 -0
  406. data/set-of-emails/maildir/bsd/x3-03.eml +59 -0
  407. data/set-of-emails/maildir/bsd/x3-04.eml +106 -0
  408. data/set-of-emails/maildir/bsd/x4-01.eml +92 -0
  409. data/set-of-emails/maildir/bsd/x4-02.eml +112 -0
  410. data/set-of-emails/maildir/bsd/x4-03.eml +245 -0
  411. data/set-of-emails/maildir/bsd/x4-04.eml +81 -0
  412. data/set-of-emails/maildir/bsd/x4-05.eml +121 -0
  413. data/set-of-emails/maildir/bsd/x4-06.eml +32 -0
  414. data/set-of-emails/maildir/bsd/x4-07.eml +153 -0
  415. data/set-of-emails/maildir/bsd/x5-01.eml +155 -0
  416. data/set-of-emails/maildir/dos/activehunter-01.eml +54 -0
  417. data/set-of-emails/maildir/dos/apachejames-01.eml +46 -0
  418. data/set-of-emails/maildir/dos/arf-01.eml +66 -0
  419. data/set-of-emails/maildir/dos/courier-01.eml +79 -0
  420. data/set-of-emails/maildir/dos/de-einsundeins-01.eml +38 -0
  421. data/set-of-emails/maildir/dos/de-gmx-01.eml +52 -0
  422. data/set-of-emails/maildir/dos/domino-01.eml +33 -0
  423. data/set-of-emails/maildir/dos/exchange-01.eml +31 -0
  424. data/set-of-emails/maildir/dos/exim-01.eml +46 -0
  425. data/set-of-emails/maildir/dos/google-apps-01.eml +66 -0
  426. data/set-of-emails/maildir/dos/imailserver-01.eml +27 -0
  427. data/set-of-emails/maildir/dos/interscanmss-01.eml +49 -0
  428. data/set-of-emails/maildir/dos/jp-biglobe-01.eml +43 -0
  429. data/set-of-emails/maildir/dos/jp-ezweb-01.eml +36 -0
  430. data/set-of-emails/maildir/dos/jp-kddi-01.eml +49 -0
  431. data/set-of-emails/maildir/dos/mailfoundry-01.eml +50 -0
  432. data/set-of-emails/maildir/dos/mailmarshalsmtp-01.eml +43 -0
  433. data/set-of-emails/maildir/dos/mcafee-01.eml +63 -0
  434. data/set-of-emails/maildir/dos/messagingserver-01.eml +102 -0
  435. data/set-of-emails/maildir/dos/mfilter-01.eml +49 -0
  436. data/set-of-emails/maildir/dos/mxlogic-01.eml +47 -0
  437. data/set-of-emails/maildir/dos/notes-01.eml +42 -0
  438. data/set-of-emails/maildir/dos/opensmtpd-01.eml +33 -0
  439. data/set-of-emails/maildir/dos/postfix-01.eml +60 -0
  440. data/set-of-emails/maildir/dos/qmail-01.eml +40 -0
  441. data/set-of-emails/maildir/dos/rfc3464-01.eml +59 -0
  442. data/set-of-emails/maildir/dos/rfc3834-01.eml +37 -0
  443. data/set-of-emails/maildir/dos/ru-mailru-01.eml +54 -0
  444. data/set-of-emails/maildir/dos/ru-yandex-01.eml +102 -0
  445. data/set-of-emails/maildir/dos/sendmail-01.eml +69 -0
  446. data/set-of-emails/maildir/dos/surfcontrol-01.eml +79 -0
  447. data/set-of-emails/maildir/dos/uk-messagelabs-01.eml +76 -0
  448. data/set-of-emails/maildir/dos/us-amazonses-01.eml +59 -0
  449. data/set-of-emails/maildir/dos/us-aol-01.eml +1258 -0
  450. data/set-of-emails/maildir/dos/us-bigfoot-01.eml +64 -0
  451. data/set-of-emails/maildir/dos/us-facebook-01.eml +40 -0
  452. data/set-of-emails/maildir/dos/us-google-01.eml +70 -0
  453. data/set-of-emails/maildir/dos/us-outlook-01.eml +72 -0
  454. data/set-of-emails/maildir/dos/us-receivingses-01.eml +74 -0
  455. data/set-of-emails/maildir/dos/us-sendgrid-01.eml +95 -0
  456. data/set-of-emails/maildir/dos/us-verizon-01.eml +31 -0
  457. data/set-of-emails/maildir/dos/us-yahoo-01.eml +78 -0
  458. data/set-of-emails/maildir/dos/us-zoho-01.eml +40 -0
  459. data/set-of-emails/maildir/dos/v5sendmail-01.eml +24 -0
  460. data/set-of-emails/maildir/dos/x1-01.eml +61 -0
  461. data/set-of-emails/maildir/dos/x2-01.eml +41 -0
  462. data/set-of-emails/maildir/dos/x3-01.eml +61 -0
  463. data/set-of-emails/maildir/dos/x4-01.eml +90 -0
  464. data/set-of-emails/maildir/dos/x5-01.eml +155 -0
  465. data/set-of-emails/maildir/err/make-test-01.eml +70 -0
  466. data/set-of-emails/maildir/err/make-test-02.eml +70 -0
  467. data/set-of-emails/maildir/err/make-test-03.eml +64 -0
  468. data/set-of-emails/maildir/err/make-test-04.eml +64 -0
  469. data/set-of-emails/maildir/err/make-test-05.eml +66 -0
  470. data/set-of-emails/maildir/err/make-test-06.eml +118 -0
  471. data/set-of-emails/maildir/err/make-test-07.eml +26 -0
  472. data/set-of-emails/maildir/err/make-test-08.eml +67 -0
  473. data/set-of-emails/maildir/err/make-test-09.eml +55 -0
  474. data/set-of-emails/maildir/err/make-test-10.eml +69 -0
  475. data/set-of-emails/maildir/err/make-test-11.eml +64 -0
  476. data/set-of-emails/maildir/err/make-test-12.eml +66 -0
  477. data/set-of-emails/maildir/err/make-test-13.eml +67 -0
  478. data/set-of-emails/maildir/err/make-test-14.eml +66 -0
  479. data/set-of-emails/maildir/err/make-test-15.eml +70 -0
  480. data/set-of-emails/maildir/err/make-test-16.eml +68 -0
  481. data/set-of-emails/maildir/err/make-test-17.eml +68 -0
  482. data/set-of-emails/maildir/err/make-test-18.eml +68 -0
  483. data/set-of-emails/maildir/err/make-test-19.eml +69 -0
  484. data/set-of-emails/maildir/err/make-test-20.eml +67 -0
  485. data/set-of-emails/maildir/err/make-test-21.eml +69 -0
  486. data/set-of-emails/maildir/err/make-test-22.eml +66 -0
  487. data/set-of-emails/maildir/err/make-test-23.eml +70 -0
  488. data/set-of-emails/maildir/err/make-test-24.eml +69 -0
  489. data/set-of-emails/maildir/err/make-test-25.eml +67 -0
  490. data/set-of-emails/maildir/err/make-test-26.eml +69 -0
  491. data/set-of-emails/maildir/err/make-test-27.eml +69 -0
  492. data/set-of-emails/maildir/err/make-test-28.eml +66 -0
  493. data/set-of-emails/maildir/err/make-test-29.eml +68 -0
  494. data/set-of-emails/maildir/err/make-test-30.eml +68 -0
  495. data/set-of-emails/maildir/err/make-test-31.eml +80 -0
  496. data/set-of-emails/maildir/err/make-test-32.eml +66 -0
  497. data/set-of-emails/maildir/err/make-test-33.eml +68 -0
  498. data/set-of-emails/maildir/err/make-test-34.eml +56 -0
  499. data/set-of-emails/maildir/err/make-test-35.eml +59 -0
  500. data/set-of-emails/maildir/err/make-test-36.eml +53 -0
  501. data/set-of-emails/maildir/err/make-test-37.eml +62 -0
  502. data/set-of-emails/maildir/mac/activehunter-01.eml +1 -2
  503. data/set-of-emails/maildir/mac/apachejames-01.eml +1 -4
  504. data/set-of-emails/maildir/mac/arf-01.eml +1 -3
  505. data/set-of-emails/maildir/mac/courier-01.eml +1 -6
  506. data/set-of-emails/maildir/mac/de-einsundeins-01.eml +1 -1
  507. data/set-of-emails/maildir/mac/de-gmx-01.eml +1 -1
  508. data/set-of-emails/maildir/mac/domino-01.eml +1 -0
  509. data/set-of-emails/maildir/mac/exchange-01.eml +1 -0
  510. data/set-of-emails/maildir/mac/exim-01.eml +1 -1
  511. data/set-of-emails/maildir/mac/google-apps-01.eml +1 -4
  512. data/set-of-emails/maildir/mac/imailserver-01.eml +1 -0
  513. data/set-of-emails/maildir/mac/interscanmss-01.eml +1 -2
  514. data/set-of-emails/maildir/mac/jp-biglobe-01.eml +1 -2
  515. data/set-of-emails/maildir/mac/jp-ezweb-01.eml +1 -1
  516. data/set-of-emails/maildir/mac/jp-kddi-01.eml +1 -2
  517. data/set-of-emails/maildir/mac/mailfoundry-01.eml +1 -2
  518. data/set-of-emails/maildir/mac/mailmarshalsmtp-01.eml +1 -2
  519. data/set-of-emails/maildir/mac/mcafee-01.eml +1 -4
  520. data/set-of-emails/maildir/mac/messagingserver-01.eml +1 -4
  521. data/set-of-emails/maildir/mac/mfilter-01.eml +1 -3
  522. data/set-of-emails/maildir/mac/mxlogic-01.eml +1 -1
  523. data/set-of-emails/maildir/mac/notes-01.eml +1 -2
  524. data/set-of-emails/maildir/mac/opensmtpd-01.eml +1 -0
  525. data/set-of-emails/maildir/mac/postfix-01.eml +1 -3
  526. data/set-of-emails/maildir/mac/qmail-01.eml +1 -1
  527. data/set-of-emails/maildir/mac/rfc3464-01.eml +1 -4
  528. data/set-of-emails/maildir/mac/rfc3834-01.eml +1 -0
  529. data/set-of-emails/maildir/mac/ru-mailru-01.eml +1 -1
  530. data/set-of-emails/maildir/mac/ru-yandex-01.eml +1 -4
  531. data/set-of-emails/maildir/mac/sendmail-01.eml +1 -4
  532. data/set-of-emails/maildir/mac/surfcontrol-01.eml +1 -5
  533. data/set-of-emails/maildir/mac/uk-messagelabs-01.eml +1 -4
  534. data/set-of-emails/maildir/mac/us-amazonses-01.eml +1 -4
  535. data/set-of-emails/maildir/mac/us-aol-01.eml +1 -15
  536. data/set-of-emails/maildir/mac/us-bigfoot-01.eml +1 -4
  537. data/set-of-emails/maildir/mac/us-facebook-01.eml +1 -4
  538. data/set-of-emails/maildir/mac/us-google-01.eml +1 -1
  539. data/set-of-emails/maildir/mac/us-outlook-01.eml +1 -4
  540. data/set-of-emails/maildir/mac/us-receivingses-01.eml +1 -4
  541. data/set-of-emails/maildir/mac/us-sendgrid-01.eml +1 -3
  542. data/set-of-emails/maildir/mac/us-verizon-01.eml +1 -2
  543. data/set-of-emails/maildir/mac/us-yahoo-01.eml +1 -1
  544. data/set-of-emails/maildir/mac/us-zoho-01.eml +1 -2
  545. data/set-of-emails/maildir/mac/v5sendmail-01.eml +1 -0
  546. data/set-of-emails/maildir/mac/x1-01.eml +1 -4
  547. data/set-of-emails/maildir/mac/x2-01.eml +1 -1
  548. data/set-of-emails/maildir/mac/x3-01.eml +1 -3
  549. data/set-of-emails/maildir/mac/x4-01.eml +1 -2
  550. data/set-of-emails/maildir/mac/x5-01.eml +1 -8
  551. data/set-of-emails/maildir/not/is-not-bounce-01.eml +25 -0
  552. data/set-of-emails/to-be-debugged-because/reason-is-onhold/onhold-0001.eml +85 -0
  553. data/set-of-emails/to-be-debugged-because/reason-is-undefined/undefined-0002.eml +27 -0
  554. data/set-of-emails/to-be-debugged-because/reason-is-undefined/undefined-0003.eml +78 -0
  555. data/set-of-emails/to-be-debugged-because/sisimai-cannot-parse-yet/cannot-parse-this-email-0002.eml +25 -0
  556. data/set-of-emails/to-be-debugged-because/something-is-wrong/issue-106-01.eml +79 -0
  557. data/set-of-emails/to-be-debugged-because/something-is-wrong/issue-106-02.eml +72 -0
  558. data/set-of-emails/to-be-debugged-because/something-is-wrong/issue-106-03.eml +68 -0
  559. data/set-of-emails/to-be-debugged-because/something-is-wrong/no-message-id-from-pr-150.eml +75 -0
  560. data/set-of-emails/to-be-parsed-for-test/README.md +20 -0
  561. data/sisimai.gemspec +25 -0
  562. metadata +647 -0
@@ -0,0 +1,82 @@
1
+ module Sisimai
2
+ # Sisimai::Mail is a handler of UNIX mbox or Maildir for reading each mail. It is
3
+ # wrapper class of Sisimai::Mail::Mbox and Sisimai::Mail::Maildir classes.
4
+ class Mail
5
+ # Imported from p5-Sisimail/lib/Sisimai/Mail.pm
6
+ @@roaccessors = [
7
+ :path, # [String] path to mbox or Maildir/
8
+ :type, # [String] Data type: mailbox, maildir, or stdin
9
+ ]
10
+ @@rwaccessors = [
11
+ :mail, # [Sisimai::Mail::Mbox, Sisimai::Mail::Maildir] Object
12
+ ]
13
+ @@roaccessors.each { |e| attr_reader e }
14
+ @@rwaccessors.each { |e| attr_accessor e }
15
+
16
+ # Constructor of Sisimai::Mail
17
+ # @param [String] argv1 Path to mbox or Maildir/
18
+ # @return [Sisimai::Mail, Nil] Object or Undef if the argument was wrong
19
+ def initialize(argv1)
20
+ classname = nil
21
+ parameter = { 'path' => argv1, 'type' => nil, 'mail' => nil }
22
+
23
+ if argv1.is_a?(::String)
24
+ # Path to mail or '<STDIN>' ?
25
+ if argv1 == '<STDIN>'
26
+ # Sisimai::Mail.new('<STDIN>')
27
+ classname = sprintf('%s::STDIN', self.class)
28
+ parameter['type'] = 'stdin'
29
+ parameter['path'] = $stdin
30
+
31
+ else
32
+ # The argumenet is a mailbox or a Maildir/.
33
+ mediatype = File.ftype(argv1)
34
+
35
+ if mediatype == 'file'
36
+ # The argument is a file, it is an mbox or email file in Maildir/
37
+ classname = sprintf('%s::Mbox', self.class)
38
+ parameter['type'] = 'mailbox'
39
+
40
+ elsif mediatype == 'directory'
41
+ # The agument is not a file, it is a Maildir/
42
+ classname = sprintf('%s::Maildir', self.class)
43
+ parameter['type'] = 'maildir'
44
+ end
45
+ end
46
+
47
+ elsif argv1.is_a?(IO)
48
+ # Read from STDIN
49
+ # The argument neither a mailbox nor a Maildir/.
50
+ classname = sprintf('%s::STDIN', self.class)
51
+ parameter['type'] = 'stdin'
52
+
53
+ end
54
+
55
+ return nil unless classname
56
+
57
+ classpath = classname.gsub('::', '/').downcase
58
+ require classpath
59
+ parameter['mail'] = Module.const_get(classname).new(parameter['path'])
60
+
61
+ @path = parameter['path']
62
+ @type = parameter['type']
63
+ @mail = parameter['mail']
64
+ end
65
+
66
+ # Mbox/Maildir reader, works as an iterator.
67
+ # @return [String] Contents of mbox/Maildir
68
+ def read
69
+ return nil unless mail
70
+ return mail.read
71
+ end
72
+
73
+ # Close the handle
74
+ # @return [True,False] true: Successfully closed the handle
75
+ # false: Mail handle is not defined
76
+ def close
77
+ return false unless mail.handle
78
+ mail.handle = nil
79
+ return true
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,85 @@
1
+ module Sisimai
2
+ class Mail
3
+ # Sisimai::Mail::Maildir is a reader for getting contents of each email in the
4
+ # Maildir/ directory.
5
+ class Maildir
6
+ # Imported from p5-Sisimail/lib/Sisimai/Mail/Maildir.pm
7
+ @@roaccessors = [
8
+ :dir, # [String] Path to Maildir/
9
+ :size, # [Integer] The number of entires in the directory
10
+ ]
11
+ @@rwaccessors = [
12
+ :path, # [String] Path to each file
13
+ :file, # [String] Each file name of a mail in the Maildir/
14
+ :inodes, # [Array] i-node List of files in the Maildir/
15
+ :offset, # [Integer] Offset position for seeking
16
+ :handle, # [IO::Dir] Directory handle
17
+ ]
18
+ @@roaccessors.each { |e| attr_reader e }
19
+ @@rwaccessors.each { |e| attr_accessor e }
20
+
21
+ # Constructor of Sisimai::Mail::Maildir
22
+ # @param [String] argvs Path to Maildir/
23
+ # @return [Sisimai::Mail::Maildir,Nil] Object or nil if the argument is
24
+ # not a directory or does not exist
25
+ def initialize(argv1)
26
+ raise Errno::ENOENT unless File.exist?(argv1)
27
+ raise Errno::ENOTDIR unless File.ftype(argv1) == 'directory'
28
+
29
+ @path = nil
30
+ @size = Dir.entries(argv1).size
31
+ @dir = argv1
32
+ @file = nil
33
+ @offset = 0
34
+ @inodes = {}
35
+ @handle = Dir.open(argv1)
36
+ end
37
+
38
+ # Maildir reader, works as a iterator.
39
+ # @return [String] Contents of file in Maildir/
40
+ def read
41
+ return nil unless self.offset < self.size
42
+
43
+ seekhandle = self.handle
44
+ filehandle = nil
45
+ readbuffer = ''
46
+ emailindir = ''
47
+ emailinode = nil
48
+
49
+ begin
50
+ while r = seekhandle.read do
51
+ # Read each file in the directory
52
+ self.offset = seekhandle.pos
53
+ next if r == '.' || r == '..'
54
+
55
+ emailindir = sprintf('%s/%s', self.dir, r)
56
+ emailindir = emailindir.squeeze('/')
57
+
58
+ next unless File.ftype(emailindir) == 'file'
59
+ next unless File.size(emailindir) > 0
60
+ next unless File.readable?(emailindir)
61
+
62
+ emailinode = File.stat(emailindir).ino
63
+ next if self.inodes.key?(emailinode)
64
+
65
+ filehandle = File.open(emailindir, 'r')
66
+ readbuffer = filehandle.read
67
+ filehandle.close
68
+
69
+ self.inodes[emailinode] = 1
70
+ self.path = emailindir
71
+ self.file = r
72
+
73
+ break
74
+ end
75
+
76
+ seekhandle.close unless self.offset < self.size
77
+ end
78
+
79
+ return readbuffer
80
+ end
81
+
82
+ end
83
+ end
84
+ end
85
+
@@ -0,0 +1,69 @@
1
+ module Sisimai
2
+ # Sisimai::Mail::Mbox is a mailbox file (UNIX mbox) reader.
3
+ class Mail
4
+ class Mbox
5
+ # Imported from p5-Sisimail/lib/Sisimai/Mail/Mbox.pm
6
+ @@roaccessors = [
7
+ :dir, # [String] Directory name of the mbox
8
+ :file, # [String] File name of the mbox
9
+ :path, # [String] Path to mbox
10
+ :size, # [Integer] File size of the mbox
11
+ ]
12
+ @@rwaccessors = [
13
+ :offset, # [Integer] Offset position for seeking
14
+ :handle, # [IO::File] File handle
15
+ ]
16
+ @@roaccessors.each { |e| attr_reader e }
17
+ @@rwaccessors.each { |e| attr_accessor e }
18
+
19
+ # Constructor of Sisimai::Mail::Mbox
20
+ # @param [String] argv1 Path to mbox
21
+ # @return [Sisimai::Mail::Mbox,Nil] Object or nil if the argument is not
22
+ # specified or does not exist
23
+ def initialize(argv1)
24
+ raise Errno::ENOENT unless File.exist?(argv1)
25
+ raise 'is not a file' unless File.ftype(argv1) == 'file'
26
+
27
+ @path = argv1
28
+ @dir = File.dirname(argv1)
29
+ @file = File.basename(argv1)
30
+ @size = File.size(argv1)
31
+ @offset = 0
32
+ @handle = File.open(argv1, 'r')
33
+ end
34
+
35
+ # Mbox reader, works as an iterator.
36
+ # @return [String] Contents of mbox
37
+ def read
38
+ return nil unless self.offset < self.size
39
+
40
+ seekoffset = self.offset || 0
41
+ filehandle = self.handle
42
+ readbuffer = ''
43
+ frombuffer = ''
44
+
45
+ begin
46
+ seekoffset = 0 if seekoffset < 0
47
+ filehandle.seek(seekoffset, 0)
48
+
49
+ filehandle.each_line do |r|
50
+ # Read the UNIX mbox file from 'From ' to the next 'From '
51
+ if r[0, 5] == 'From ' && readbuffer.size > 0
52
+ frombuffer = r
53
+ break
54
+ end
55
+ readbuffer << r
56
+ end
57
+
58
+ seekoffset = filehandle.pos - frombuffer.bytesize
59
+ frombuffer = ''
60
+ self.offset = seekoffset
61
+ filehandle.close unless self.offset < self.size
62
+ end
63
+
64
+ return readbuffer.to_s
65
+ end
66
+ end
67
+ end
68
+ end
69
+
@@ -0,0 +1,52 @@
1
+ # Sisimai::Mail::STDIN is a reader for getting contents of each email from STDIN
2
+ module Sisimai
3
+ class Mail
4
+ class STDIN
5
+ # Imported from p5-Sisimail/lib/Sisimai/Mail/STDIN.pm
6
+ @@roaccessors = [
7
+ :path, # [String] Path to mbox
8
+ :name, # [String] File name of the mbox
9
+ :size, # [Integer] File size of the mbox
10
+ ]
11
+ @@rwaccessors = [
12
+ :offset, # [Integer] Offset position for seeking
13
+ :handle, # [IO::File] File handle
14
+ ]
15
+ @@roaccessors.each do |e| attr_reader e end
16
+ @@rwaccessors.each do |e| attr_accessor e end
17
+
18
+ # Constructor of Sisimai::Mail::STDIN
19
+ # @param [IO::STDIN] stdin Standard-In
20
+ # @return [Sisimai::Mail::STDIN] Object
21
+ def initialize(stdin = $stdin)
22
+ raise 'is not an IO object' unless stdin.is_a?(IO)
23
+
24
+ @path = '<STDIN>'
25
+ @name = '<STDIN>'
26
+ @size = nil
27
+ @offset = 0
28
+ @handle = stdin
29
+ end
30
+
31
+ # Mbox reader, works as a iterator.
32
+ # @return [String] Contents of mbox
33
+ def read
34
+ readhandle = self.handle
35
+ readbuffer = ''
36
+
37
+ begin
38
+ readhandle = STDIN unless readhandle
39
+ while r = readhandle.gets
40
+ break if readbuffer.size > 0 && r[0, 5] == 'From '
41
+ readbuffer << r
42
+ end
43
+ ensure
44
+ readhandle.close
45
+ end
46
+
47
+ return readbuffer
48
+ end
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1,152 @@
1
+ module Sisimai
2
+ # Sisimai::MDA - Error message parser for MDA
3
+ module MDA
4
+ # Imported from p5-Sisimail/lib/Sisimai/MDA.pm
5
+ class << self
6
+ Re0 = {
7
+ :from => %r/\A(?:Mail Delivery Subsystem|MAILER-DAEMON|postmaster)/i,
8
+ }
9
+ Re1 = {
10
+ # dovecot/src/deliver/deliver.c
11
+ # 11: #define DEFAULT_MAIL_REJECTION_HUMAN_REASON \
12
+ # 12: "Your message to <%t> was automatically rejected:%n%r"
13
+ 'dovecot' => %r/\AYour message to .+ was automatically rejected:\z/,
14
+ 'mail.local' => %r/\Amail[.]local: /,
15
+ 'procmail' => %r/\Aprocmail: /,
16
+ 'maildrop' => %r/\Amaildrop: /,
17
+ 'vpopmail' => %r/\Avdelivermail: /,
18
+ 'vmailmgr' => %r/\Avdeliver: /,
19
+ }
20
+ Re2 = %r{\A(?>
21
+ Your[ ]message[ ]to[ ].+[ ]was[ ]automatically[ ]rejected:\z
22
+ |(?:mail[.]local|procmail|maildrop|vdelivermail|vdeliver):[ ]
23
+ )
24
+ }x
25
+
26
+ # dovecot/src/deliver/mail-send.c:94
27
+ ReFailure = {
28
+ 'dovecot' => {
29
+ 'userunknown' => %r/\AMailbox doesn't exist: /i,
30
+ 'mailboxfull' => %r{\A(?:
31
+ Quota[ ]exceeded # Dovecot 1.2 dovecot/src/plugins/quota/quota.c
32
+ |Quota[ ]exceeded[ ][(]mailbox[ ]for[ ]user[ ]is[ ]full[)] # dovecot/src/plugins/quota/quota.c
33
+ |Not[ ]enough[ ]disk[ ]space
34
+ )
35
+ }xi,
36
+ },
37
+ 'mail.local' => {
38
+ 'userunknown' => %r{[:][ ](?:
39
+ unknown[ ]user[:]
40
+ |User[ ]unknown
41
+ |Invalid[ ]mailbox[ ]path
42
+ |User[ ]missing[ ]home[ ]directory
43
+ )
44
+ }xi,
45
+ 'mailboxfull' => %r{(?:
46
+ Disc[ ]quota[ ]exceeded
47
+ |Mailbox[ ]full[ ]or[ ]quota[ ]exceeded
48
+ )
49
+ }xi,
50
+ 'systemerror' => %r/Temporary file write error/i,
51
+ },
52
+ 'procmail' => {
53
+ 'mailboxfull' => %r/Quota exceeded while writing/i,
54
+ 'systemfull' => %r/No space left to finish writing/i,
55
+ },
56
+ 'maildrop' => {
57
+ 'userunknown' => %r{(?:
58
+ Invalid[ ]user[ ]specified[.]
59
+ |Cannot[ ]find[ ]system[ ]user
60
+ )
61
+ }xi,
62
+ 'mailboxfull' => %r/maildir over quota[.]\z/i,
63
+ },
64
+ 'vpopmail' => {
65
+ 'userunknown' => %r/Sorry, no mailbox here by that name[.]/i,
66
+ 'filtered' => %r{(?:
67
+ account[ ]is[ ]locked[ ]email[ ]bounced
68
+ |user[ ]does[ ]not[ ]exist,[ ]but[ ]will[ ]deliver[ ]to[ ]
69
+ )
70
+ }xi,
71
+ 'mailboxfull' => %r/(?:domain|user) is over quota/i,
72
+ },
73
+ 'vmailmgr' => {
74
+ 'userunknown' => %r{(?>
75
+ Invalid[ ]or[ ]unknown[ ](?:base[ ]user[ ]or[ ]domain|virtual[ ]user)
76
+ |User[ ]name[ ]does[ ]not[ ]refer[ ]to[ ]a[ ]virtual[ ]user/
77
+ )
78
+ }ix,
79
+ 'mailboxfull' => %r/Delivery failed due to system quota violation/i,
80
+ },
81
+ }
82
+
83
+ # Parse message body and return reason and text
84
+ # @param [Hash] mhead Message header of a bounce email
85
+ # @options mhead [String] from From header
86
+ # @options mhead [String] date Date header
87
+ # @options mhead [String] subject Subject header
88
+ # @options mhead [Array] received Received headers
89
+ # @options mhead [String] others Other required headers
90
+ # @param [String] mbody Message body of a bounce email
91
+ # @return [Hash, Nil] Bounce data list and message/rfc822 part
92
+ # or Undef if it failed to parse or the
93
+ # arguments are missing
94
+ def scan(mhead, mbody)
95
+ return nil unless mhead
96
+ return nil unless mbody
97
+ return nil if mhead.keys.size == 0
98
+ return nil if mbody.empty?
99
+
100
+ return nil unless mhead['from'] =~ Re0[:from]
101
+
102
+ agentname0 = '' # [String] MDA name
103
+ reasonname = '' # [String] Error reason
104
+ bouncemesg = '' # [String] Error message
105
+ hasdivided = mbody.split("\n")
106
+ linebuffer = []
107
+
108
+ hasdivided.each do |e|
109
+ # Check each line with each MDA's symbol regular expression.
110
+ if agentname0 == ''
111
+ # Try to match with each regular expression
112
+ next unless e.size > 0;
113
+ next unless e =~ Re2
114
+
115
+ Re1.each_key do |f|
116
+ # Detect the agent name from the line
117
+ next unless e =~ Re1[f]
118
+ agentname0 = f
119
+ break
120
+ end
121
+ end
122
+
123
+ # Append error message lines to @linebuffer
124
+ linebuffer << e
125
+ break unless e.size > 0
126
+ end
127
+
128
+ return nil unless agentname0.size > 0
129
+ return nil unless linebuffer.size > 0
130
+
131
+ ReFailure[agentname0].each_key do |e|
132
+ # Detect an error reason from message patterns of the MDA.
133
+ linebuffer.each do |f|
134
+ # Try to match with each regular expression
135
+ next unless f =~ ReFailure[agentname0][e]
136
+ reasonname = e
137
+ bouncemesg = f
138
+ break
139
+ end
140
+ break if bouncemesg.size > 0 && reasonname.size > 0
141
+ end
142
+
143
+ return {
144
+ 'mda' => agentname0,
145
+ 'reason' => reasonname || '',
146
+ 'message' => bouncemesg || '',
147
+ }
148
+ end
149
+ end
150
+ end
151
+ end
152
+
@@ -0,0 +1,510 @@
1
+ module Sisimai
2
+ # Sisimai::Message convert bounce email text to data structure. It resolve email
3
+ # text into an UNIX From line, the header part of the mail, delivery status, and
4
+ # RFC822 header part. When the email given as a argument of "new" method is not a
5
+ # bounce email, the method returns nil.
6
+ class Message
7
+ # Imported from p5-Sisimail/lib/Sisimai/Message.pm
8
+ require 'sisimai/arf'
9
+ require 'sisimai/mime'
10
+ require 'sisimai/order'
11
+ require 'sisimai/string'
12
+ require 'sisimai/rfc3834'
13
+ require 'sisimai/rfc5322'
14
+
15
+ @@rwaccessors = [
16
+ :from, # [String] UNIX From line
17
+ :header, # [Hash] Header part of a email
18
+ :ds, # [Array] Parsed data by Sisimai::MTA::*
19
+ :rfc822, # [Hash] Header part of the original message
20
+ ]
21
+ @@rwaccessors.each { |e| attr_accessor e }
22
+
23
+ EndOfEmail = Sisimai::String.EOM
24
+ RFC822Head = Sisimai::RFC5322.HEADERFIELDS
25
+ RFC3834Set = Sisimai::RFC3834.headerlist.map { |e| e.downcase }
26
+ HeaderList = [
27
+ 'from', 'to', 'date', 'subject', 'content-type', 'reply-to', 'message-id',
28
+ 'received', 'content-transfer-encoding', 'return-path', 'x-mailer',
29
+ ]
30
+ MultiHeads = { 'received' => true }
31
+ IgnoreList = { 'dkim-signature' => true }
32
+ Indicators = {
33
+ :begin => ( 1 << 1 ),
34
+ :endof => ( 1 << 2 ),
35
+ }
36
+ @@DefaultSet = Sisimai::Order.another
37
+ @@PatternSet = Sisimai::Order.by('subject')
38
+ @@ExtHeaders = Sisimai::Order.headers
39
+ @@ToBeLoaded = []
40
+ @@TryOnFirst = []
41
+
42
+ # Constructor of Sisimai::Message
43
+ # @param [String] data Email text data
44
+ # @param [Hash] argvs Module to be loaded
45
+ # @options argvs [String] data Entire email message
46
+ # @return [Sisimai::Message] Structured email data or Undef if each
47
+ # value of the arguments are missing
48
+ def initialize(data: '', **argvs)
49
+ return nil if data.empty?
50
+
51
+ email = data
52
+ email = email.scrub('?')
53
+ email = email.gsub("\r\n", "\n")
54
+ methodargv = { 'data' => email }
55
+
56
+ [:'load', :'order'].each do |e|
57
+ # Order of MTA, MSP modules
58
+ next unless argvs.key?(e)
59
+ next unless argvs[e].is_a? Array
60
+ next if argvs[e].empty?
61
+ methodargv[e.to_s] = argvs[e]
62
+ end
63
+
64
+ parameters = Sisimai::Message.make(methodargv)
65
+ return nil unless parameters
66
+ return nil unless parameters.key?('ds')
67
+
68
+ @from = parameters['from']
69
+ @header = parameters['header']
70
+ @ds = parameters['ds']
71
+ @rfc822 = parameters['rfc822']
72
+ end
73
+
74
+ # Check whether the object has valid content or not
75
+ # @return [True,False] returns true if the object is void
76
+ def void
77
+ return true unless @ds
78
+ return false
79
+ end
80
+
81
+ # Make data structure from the email message(a body part and headers)
82
+ # @param [Hash] argvs Email data
83
+ # @options argvs [String] data Entire email message
84
+ # @return [Hash] Resolved data structure
85
+ def self.make(argvs)
86
+ email = argvs['data']
87
+
88
+ processing = { 'from' => '', 'header' => {}, 'rfc822' => '', 'ds' => [] }
89
+ mtamodules = []
90
+
91
+ ['load', 'order'].each do |e|
92
+ # The order of MTA modules specified by user
93
+ next unless argvs.key?(e)
94
+ next unless argvs[e].is_a? Array
95
+ next if argvs[e].empty?
96
+
97
+ mtamodules.concat(argvs['order']) if e == 'order'
98
+ next unless e == 'load'
99
+
100
+ # Load user defined MTA module
101
+ argvs['load'].each do |v|
102
+ # Load user defined MTA module
103
+ begin
104
+ require v.to_s.gsub('::', '/').downcase
105
+ rescue LoadError
106
+ warn ' ***warning: Failed to load ' + v
107
+ next
108
+ end
109
+
110
+ Module.const_get(v).headerlist.each do |w|
111
+ # Get header name which required user defined MTA module
112
+ @@ExtHeaders[w] ||= {}
113
+ @@ExtHeaders[w][v] = 1
114
+ end
115
+ @@ToBeLoaded << v
116
+ end
117
+ end
118
+
119
+ mtamodules.each do |e|
120
+ # Append the custom order of MTA modules
121
+ next if @@ToBeLoaded.index(e)
122
+ @@ToBeLoaded << e
123
+ end
124
+
125
+ # 0. Split email data to headers and a body part.
126
+ aftersplit = Sisimai::Message.divideup(email)
127
+ return nil if aftersplit.empty?
128
+
129
+ # 1. Initialize variables for setting the value of each email header.
130
+ @@TryOnFirst = []
131
+
132
+ # 2. Convert email headers from text to hash reference
133
+ processing['from'] = aftersplit['from']
134
+ processing['header'] = Sisimai::Message.headers(aftersplit['header'])
135
+
136
+ # 3. Check headers for detecting MTA/MSP module
137
+ if @@TryOnFirst.empty?
138
+ @@TryOnFirst.concat(Sisimai::Message.makeorder(processing['header']))
139
+ end
140
+
141
+ # 4. Rewrite message body for detecting the bounce reason
142
+ methodargv = { 'mail' => processing, 'body' => aftersplit['body'] }
143
+ bouncedata = Sisimai::Message.parse(methodargv)
144
+
145
+ return nil unless bouncedata
146
+ return nil if bouncedata.empty?
147
+ processing['ds'] = bouncedata['ds']
148
+
149
+ # 5. Rewrite headers of the original message in the body part
150
+ rfc822part = bouncedata['rfc822']
151
+ rfc822part = aftersplit['body'] if rfc822part.empty?
152
+ processing['rfc822'] = Sisimai::Message.takeapart(rfc822part)
153
+
154
+ return processing
155
+ end
156
+
157
+ # Divide email data up headers and a body part.
158
+ # @param [String] email Email data
159
+ # @return [Hash] Email data after split
160
+ def self.divideup(email)
161
+ return {} if email.empty?
162
+
163
+ email = email.scrub('?')
164
+ email = email.gsub(/[ \t]+$/, '')
165
+ email = email.gsub(/^[ \t]+$/, '')
166
+ hasdivided = email.split("\n")
167
+ return {} if hasdivided.empty?
168
+
169
+ readcursor = 0
170
+ aftersplit = { 'from' => '', 'header' => '', 'body' => '' }
171
+ pseudofrom = 'MAILER-DAEMON Tue Feb 11 00:00:00 2014'
172
+
173
+ if hasdivided[0][0, 5] == 'From '
174
+ # From MAILER-DAEMON Tue Feb 11 00:00:00 2014
175
+ aftersplit['from'] = hasdivided.shift
176
+ aftersplit['from'] = aftersplit['from'].delete("\n").delete("\r")
177
+ end
178
+
179
+ # Split email data to headers and a body part.
180
+ hasdivided.each do |e|
181
+ # Split email data to headers and a body part.
182
+ e = e.delete("\r").delete("\n")
183
+
184
+ if readcursor & Indicators[:endof] > 0
185
+ # The body part of the email
186
+ aftersplit['body'] += e + "\n"
187
+
188
+ else
189
+ # The boundary for splitting headers and a body part does not
190
+ # appeare yet.
191
+ if e.empty?
192
+ # Blank line, it is a boundary of headers and a body part
193
+ readcursor |= Indicators[:endof] if readcursor & Indicators[:begin] > 0
194
+
195
+ else
196
+ # The header part of the email
197
+ aftersplit['header'] += e + "\n"
198
+ readcursor |= Indicators[:begin]
199
+ end
200
+ end
201
+ end
202
+ return {} if aftersplit['header'].empty?
203
+ return {} if aftersplit['body'].empty?
204
+
205
+ aftersplit['from'] = pseudofrom if aftersplit['from'].empty?
206
+ return aftersplit
207
+ end
208
+
209
+ # Convert email headers from text to hash reference
210
+ # @param [String] heads Email header data
211
+ # @return [Hash] Structured email header data
212
+ def self.headers(heads)
213
+ return nil unless heads
214
+
215
+ currheader = ''
216
+ allheaders = {}
217
+ structured = {}
218
+
219
+ HeaderList.each { |e| structured[e] = nil }
220
+ HeaderList.each { |e| allheaders[e] = true }
221
+ RFC3834Set.each { |e| allheaders[e] = true }
222
+ MultiHeads.each_key { |e| structured[e.downcase] = [] }
223
+ @@ExtHeaders.each_key { |e| allheaders[e] = true }
224
+
225
+ heads.split("\n").each do |e|
226
+ # Convert email headers to hash
227
+ if cv = e.match(/\A([^ ]+?)[:][ ]*(.+?)\z/)
228
+ # split the line into a header name and a header content
229
+ lhs = cv[1]
230
+ rhs = cv[2]
231
+
232
+ currheader = lhs.downcase
233
+ next unless allheaders.key?(currheader)
234
+
235
+ if MultiHeads.key?(currheader)
236
+ # Such as 'Received' header, there are multiple headers in a single
237
+ # email message.
238
+ rhs = rhs.tr("\t", ' ')
239
+ rhs = rhs.squeeze(' ')
240
+ structured[currheader] << rhs
241
+
242
+ else
243
+ # Other headers except "Received" and so on
244
+ if @@ExtHeaders[currheader]
245
+ # MTA specific header
246
+ @@TryOnFirst.concat(@@ExtHeaders[currheader].keys)
247
+ end
248
+ structured[currheader] = rhs
249
+ end
250
+
251
+ elsif cv = e.match(/\A[ \t]+(.+?)\z/)
252
+ # Ignore header?
253
+ next if IgnoreList[currheader]
254
+
255
+ # Header line continued from the previous line
256
+ if structured[currheader].is_a? Array
257
+ # Concatenate a header which have multi-lines such as 'Received'
258
+ structured[currheader][-1] += ' ' + cv[1]
259
+
260
+ else
261
+ structured[currheader] ||= ''
262
+ structured[currheader] += ' ' + cv[1]
263
+ end
264
+ end
265
+ end
266
+ return structured
267
+ end
268
+
269
+ # Check headers for detecting MTA/MSP module and returns the order of modules
270
+ # @param [Hash] heads Email header data
271
+ # @return [Array] Order of MTA/MSP modules
272
+ def self.makeorder(heads)
273
+ return [] unless heads
274
+ return [] unless heads['subject']
275
+ return [] if heads['subject'].empty?
276
+ order = []
277
+
278
+ # Try to match the value of "Subject" with patterns generated by
279
+ # Sisimai::Order->by('subject') method
280
+ @@PatternSet.each_key do |e|
281
+ # Get MTA list from the subject header
282
+ next unless heads['subject'] =~ e
283
+
284
+ # Matched and push MTA list
285
+ order.concat(@@PatternSet[e])
286
+ break
287
+ end
288
+ return order
289
+ end
290
+
291
+ # Take each email header in the original message apart
292
+ # @param [String] heads The original message header
293
+ # @return [Hash] Structured message headers
294
+ def self.takeapart(heads)
295
+ return {} unless heads
296
+
297
+ # Convert from string to hash reference
298
+ heads = heads.gsub(/^[>]+[ ]/m, '')
299
+
300
+ takenapart = {}
301
+ hasdivided = heads.split("\n")
302
+ previousfn = '' # Previous field name
303
+ borderline = '__MIME_ENCODED_BOUNDARY__'
304
+ mimeborder = {}
305
+
306
+ hasdivided.each do |e|
307
+ # Header name as a key, The value of header as a value
308
+ if cv = e.match(/\A([-0-9A-Za-z]+?)[:][ ]*(.*)\z/)
309
+ # Header
310
+ lhs = cv[1].downcase
311
+ rhs = cv[2]
312
+ previousfn = ''
313
+
314
+ next unless RFC822Head.key?(lhs)
315
+ previousfn = lhs
316
+ takenapart[previousfn] = rhs unless takenapart[previousfn]
317
+
318
+ else
319
+ # Continued line from the previous line
320
+ next unless e =~ /\A[ \t]+/
321
+ next if previousfn.empty?
322
+
323
+ # Concatenate the line if it is the value of required header
324
+ if Sisimai::MIME.is_mimeencoded(e)
325
+ # The line is MIME-Encoded test
326
+ if previousfn == 'subject'
327
+ # Subject: header
328
+ takenapart[previousfn] += borderline + e
329
+
330
+ else
331
+ # Is not Subject header
332
+ takenapart[previousfn] += e
333
+ end
334
+ mimeborder[previousfn] = true
335
+
336
+ else
337
+ # ASCII Characters only: Not MIME-Encoded
338
+ e = e.lstrip
339
+ takenapart[previousfn] += e
340
+ mimeborder[previousfn] ||= false
341
+ end
342
+ end
343
+ end
344
+
345
+ if takenapart['subject']
346
+ # Convert MIME-Encoded subject
347
+ v = takenapart['subject']
348
+
349
+ if Sisimai::String.is_8bit(v)
350
+ # The value of ``Subject'' header is including multibyte character,
351
+ # is not MIME-Encoded text.
352
+ v = 'MULTIBYTE CHARACTERS HAVE BEEN REMOVED'
353
+
354
+ else
355
+ # MIME-Encoded subject field or ASCII characters only
356
+ r = []
357
+ if mimeborder['subject']
358
+ # split the value of Subject by $borderline
359
+ v.split(borderline).each do |m|
360
+ # Insert value to the array if the string is MIME encoded text
361
+ r << m if Sisimai::MIME.is_mimeencoded(m)
362
+ end
363
+ else
364
+ # Subject line is not MIME encoded
365
+ r << v
366
+ end
367
+ v = Sisimai::MIME.mimedecode(r)
368
+ end
369
+ takenapart['subject'] = v
370
+ end
371
+ return takenapart
372
+ end
373
+
374
+ # Parse bounce mail with each MTA/MSP module
375
+ # @param [Hash] argvs Processing message entity.
376
+ # @param options argvs [Hash] mail Email message entity
377
+ # @param options mail [String] from From line of mbox
378
+ # @param options mail [Hash] header Email header data
379
+ # @param options mail [String] rfc822 Original message part
380
+ # @param options mail [Array] ds Delivery status list(parsed data)
381
+ # @param options argvs [String] body Email message body
382
+ # @param options argvs [Array] load MTA/MSP module list to load on first
383
+ # @return [Hash] Parsed and structured bounce mails
384
+ def self.parse(argvs)
385
+ mesgentity = argvs['mail']
386
+ bodystring = argvs['body']
387
+ mailheader = mesgentity['header']
388
+
389
+ return nil unless argvs['mail']
390
+ return nil unless argvs['body']
391
+
392
+ # PRECHECK_EACH_HEADER:
393
+ # Set empty string if the value is nil
394
+ mailheader['from'] ||= ''
395
+ mailheader['subject'] ||= ''
396
+ mailheader['content-type'] ||= ''
397
+
398
+ # Decode BASE64 Encoded message body, rewrite.
399
+ mesgformat = (mailheader['content-type'] || '').downcase
400
+ ctencoding = (mailheader['content-transfer-encoding'] || '').downcase
401
+
402
+ if mesgformat =~ %r|text/plain;|
403
+ # Content-Type: text/plain; charset=UTF-8
404
+ if ctencoding == 'base64' || ctencoding == 'quoted-printable'
405
+ # Content-Transfer-Encoding: base64
406
+ # Content-Transfer-Encoding: quoted-printable
407
+ if ctencoding == 'base64'
408
+ # Content-Transfer-Encoding: base64
409
+ bodystring = Sisimai::MIME.base64d(bodystring)
410
+
411
+ else
412
+ # Content-Transfer-Encoding: quoted-printable
413
+ bodystring = Sisimai::MIME.qprintd(bodystring)
414
+ end
415
+ end
416
+ end
417
+
418
+ # EXPAND_FORWARDED_MESSAGE:
419
+ # Check whether or not the message is a bounce mail.
420
+ # Pre-Process email body if it is a forwarded bounce message.
421
+ # Get the original text when the subject begins from 'fwd:' or 'fw:'
422
+ if mailheader['subject'] =~ /\A[ \t]*fwd?:/i
423
+ # Delete quoted strings, quote symbols(>)
424
+ bodystring = bodystring.gsub(/^[>]+[ ]/m, '')
425
+ bodystring = bodystring.gsub(/^[>]$/m, '')
426
+ end
427
+ bodystring += EndOfEmail
428
+ haveloaded = {}
429
+ scannedset = nil
430
+
431
+ catch :SCANNER do
432
+ loop do
433
+ # 1. Sisimai::ARF
434
+ # 2. User-Defined Module
435
+ # 3. MTA Module Candidates to be tried on first
436
+ # 4. Sisimai::MTA::* and MSP::*
437
+ # 5. Sisimai::RFC3464
438
+ # 6. Sisimai::RFC3834
439
+ #
440
+ if Sisimai::ARF.is_arf(mailheader)
441
+ # Feedback Loop message
442
+ scannedset = Sisimai::ARF.scan(mailheader, bodystring)
443
+ throw :SCANNER if scannedset
444
+ end
445
+
446
+ @@ToBeLoaded.each do |r|
447
+ # Call user defined MTA modules
448
+ next if haveloaded[r]
449
+ begin
450
+ require r.gsub('::', '/').downcase
451
+ rescue LoadError => ce
452
+ warn ' ***warning: Failed to load ' + ce.to_s
453
+ next
454
+ end
455
+ scannedset = Module.const_get(r).scan(mailheader, bodystring)
456
+ haveloaded[r] = true
457
+ throw :SCANNER if scannedset
458
+ end
459
+
460
+ @@TryOnFirst.each do |r|
461
+ # Try MTA module candidates which are detected from MTA specific
462
+ # mail headers on first
463
+ next if haveloaded.key?(r)
464
+ begin
465
+ require r.gsub('::', '/').downcase
466
+ rescue LoadError => ce
467
+ warn ' ***warning: ' + ce.to_s
468
+ next
469
+ end
470
+ scannedset = Module.const_get(r).scan(mailheader, bodystring)
471
+ haveloaded[r] = true
472
+ throw :SCANNER if scannedset
473
+ end
474
+
475
+ @@DefaultSet.each do |r|
476
+ # MTA/MSP modules which does not have MTA specific header and did
477
+ # not match with any regular expressions of Subject header.
478
+ next if haveloaded.key?(r)
479
+ begin
480
+ scannedset = Module.const_get(r).scan(mailheader, bodystring)
481
+ haveloaded[r] = true
482
+ throw :SCANNER if scannedset
483
+ rescue => ce
484
+ warn ' ***warning: ' + ce.to_s
485
+ next
486
+ end
487
+
488
+ end
489
+
490
+ # When the all of Sisimai::MTA::* modules did not return bounce data,
491
+ # call Sisimai::RFC3464;
492
+ require 'sisimai/rfc3464'
493
+ scannedset = Sisimai::RFC3464.scan(mailheader, bodystring)
494
+ break if scannedset
495
+
496
+ # Try to parse the message as auto reply message defined in RFC3834
497
+ require 'sisimai/rfc3834'
498
+ scannedset = Sisimai::RFC3834.scan(mailheader, bodystring)
499
+ break if scannedset
500
+
501
+ # as of now, we have no sample email for coding this block
502
+ break
503
+ end
504
+ end
505
+ return scannedset
506
+ end
507
+
508
+ end
509
+ end
510
+