sisimai 4.25.16 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (177) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -3
  3. data/ANALYTICAL-PRECISION +2 -2
  4. data/Benchmarks.mk +3 -3
  5. data/CONTRIBUTING +1 -1
  6. data/ChangeLog.md +412 -393
  7. data/Developers.mk +5 -6
  8. data/Gemfile +1 -1
  9. data/Makefile +15 -15
  10. data/README-JA.md +140 -78
  11. data/README.md +290 -143
  12. data/Rakefile +9 -3
  13. data/Repository.mk +2 -3
  14. data/lib/sisimai/address.rb +118 -74
  15. data/lib/sisimai/arf.rb +84 -82
  16. data/lib/sisimai/datetime.rb +5 -52
  17. data/lib/sisimai/{data → fact}/json.rb +7 -9
  18. data/lib/sisimai/fact/yaml.rb +31 -0
  19. data/lib/sisimai/fact.rb +468 -0
  20. data/lib/sisimai/lhost/activehunter.rb +12 -14
  21. data/lib/sisimai/lhost/amavis.rb +11 -14
  22. data/lib/sisimai/lhost/amazonses.rb +37 -41
  23. data/lib/sisimai/lhost/amazonworkmail.rb +15 -18
  24. data/lib/sisimai/lhost/aol.rb +12 -14
  25. data/lib/sisimai/lhost/apachejames.rb +19 -21
  26. data/lib/sisimai/lhost/barracuda.rb +10 -12
  27. data/lib/sisimai/lhost/bigfoot.rb +21 -21
  28. data/lib/sisimai/lhost/biglobe.rb +15 -16
  29. data/lib/sisimai/lhost/courier.rb +20 -20
  30. data/lib/sisimai/lhost/domino.rb +23 -19
  31. data/lib/sisimai/lhost/einsundeins.rb +23 -18
  32. data/lib/sisimai/lhost/exchange2003.rb +30 -29
  33. data/lib/sisimai/lhost/exchange2007.rb +70 -58
  34. data/lib/sisimai/lhost/exim.rb +175 -161
  35. data/lib/sisimai/lhost/ezweb.rb +31 -56
  36. data/lib/sisimai/lhost/facebook.rb +21 -33
  37. data/lib/sisimai/lhost/fml.rb +43 -48
  38. data/lib/sisimai/lhost/gmail.rb +29 -29
  39. data/lib/sisimai/lhost/gmx.rb +18 -17
  40. data/lib/sisimai/lhost/googlegroups.rb +9 -10
  41. data/lib/sisimai/lhost/gsuite.rb +21 -27
  42. data/lib/sisimai/lhost/imailserver.rb +25 -39
  43. data/lib/sisimai/lhost/interscanmss.rb +28 -31
  44. data/lib/sisimai/lhost/kddi.rb +22 -28
  45. data/lib/sisimai/lhost/mailfoundry.rb +11 -12
  46. data/lib/sisimai/lhost/mailmarshalsmtp.rb +25 -29
  47. data/lib/sisimai/lhost/mailru.rb +33 -27
  48. data/lib/sisimai/lhost/mcafee.rb +21 -31
  49. data/lib/sisimai/lhost/messagelabs.rb +17 -20
  50. data/lib/sisimai/lhost/messagingserver.rb +40 -37
  51. data/lib/sisimai/lhost/mfilter.rb +15 -16
  52. data/lib/sisimai/lhost/mxlogic.rb +24 -23
  53. data/lib/sisimai/lhost/notes.rb +17 -17
  54. data/lib/sisimai/lhost/office365.rb +63 -27
  55. data/lib/sisimai/lhost/opensmtpd.rb +12 -13
  56. data/lib/sisimai/lhost/outlook.rb +12 -15
  57. data/lib/sisimai/lhost/postfix.rb +179 -129
  58. data/lib/sisimai/lhost/powermta.rb +12 -14
  59. data/lib/sisimai/lhost/qmail.rb +44 -47
  60. data/lib/sisimai/lhost/receivingses.rb +15 -20
  61. data/lib/sisimai/lhost/sendgrid.rb +34 -32
  62. data/lib/sisimai/lhost/sendmail.rb +66 -53
  63. data/lib/sisimai/lhost/surfcontrol.rb +19 -19
  64. data/lib/sisimai/lhost/v5sendmail.rb +45 -39
  65. data/lib/sisimai/lhost/verizon.rb +35 -39
  66. data/lib/sisimai/lhost/x1.rb +18 -17
  67. data/lib/sisimai/lhost/x2.rb +17 -14
  68. data/lib/sisimai/lhost/x3.rb +19 -19
  69. data/lib/sisimai/lhost/x4.rb +72 -57
  70. data/lib/sisimai/lhost/x5.rb +17 -19
  71. data/lib/sisimai/lhost/x6.rb +41 -17
  72. data/lib/sisimai/lhost/yahoo.rb +17 -16
  73. data/lib/sisimai/lhost/yandex.rb +16 -20
  74. data/lib/sisimai/lhost/zoho.rb +16 -15
  75. data/lib/sisimai/lhost.rb +8 -10
  76. data/lib/sisimai/mail/maildir.rb +1 -3
  77. data/lib/sisimai/mail/mbox.rb +3 -4
  78. data/lib/sisimai/mail/memory.rb +0 -1
  79. data/lib/sisimai/mail/stdin.rb +1 -3
  80. data/lib/sisimai/mail.rb +3 -7
  81. data/lib/sisimai/mda.rb +28 -42
  82. data/lib/sisimai/message.rb +435 -326
  83. data/lib/sisimai/order.rb +5 -5
  84. data/lib/sisimai/reason/authfailure.rb +64 -0
  85. data/lib/sisimai/reason/badreputation.rb +53 -0
  86. data/lib/sisimai/reason/blocked.rb +94 -160
  87. data/lib/sisimai/reason/contenterror.rb +8 -9
  88. data/lib/sisimai/reason/delivered.rb +4 -6
  89. data/lib/sisimai/reason/exceedlimit.rb +10 -12
  90. data/lib/sisimai/reason/expired.rb +6 -8
  91. data/lib/sisimai/reason/feedback.rb +2 -3
  92. data/lib/sisimai/reason/filtered.rb +17 -19
  93. data/lib/sisimai/reason/hasmoved.rb +9 -10
  94. data/lib/sisimai/reason/hostunknown.rb +15 -15
  95. data/lib/sisimai/reason/mailboxfull.rb +10 -12
  96. data/lib/sisimai/reason/mailererror.rb +18 -20
  97. data/lib/sisimai/reason/mesgtoobig.rb +9 -11
  98. data/lib/sisimai/reason/networkerror.rb +5 -8
  99. data/lib/sisimai/reason/norelaying.rb +8 -11
  100. data/lib/sisimai/reason/notaccept.rb +13 -14
  101. data/lib/sisimai/reason/notcompliantrfc.rb +43 -0
  102. data/lib/sisimai/reason/onhold.rb +6 -9
  103. data/lib/sisimai/reason/policyviolation.rb +14 -12
  104. data/lib/sisimai/reason/rejected.rb +26 -24
  105. data/lib/sisimai/reason/requireptr.rb +69 -0
  106. data/lib/sisimai/reason/securityerror.rb +33 -36
  107. data/lib/sisimai/reason/spamdetected.rb +114 -147
  108. data/lib/sisimai/reason/speeding.rb +49 -0
  109. data/lib/sisimai/reason/suspend.rb +11 -11
  110. data/lib/sisimai/reason/syntaxerror.rb +11 -10
  111. data/lib/sisimai/reason/systemerror.rb +7 -9
  112. data/lib/sisimai/reason/systemfull.rb +7 -8
  113. data/lib/sisimai/reason/toomanyconn.rb +9 -11
  114. data/lib/sisimai/reason/undefined.rb +2 -3
  115. data/lib/sisimai/reason/userunknown.rb +129 -146
  116. data/lib/sisimai/reason/vacation.rb +3 -4
  117. data/lib/sisimai/reason/virusdetected.rb +10 -11
  118. data/lib/sisimai/reason.rb +59 -64
  119. data/lib/sisimai/rfc1894.rb +55 -28
  120. data/lib/sisimai/rfc2045.rb +373 -0
  121. data/lib/sisimai/rfc3464.rb +250 -308
  122. data/lib/sisimai/rfc3834.rb +42 -45
  123. data/lib/sisimai/rfc5322.rb +75 -100
  124. data/lib/sisimai/rfc5965.rb +31 -0
  125. data/lib/sisimai/rhost/cox.rb +5 -6
  126. data/lib/sisimai/rhost/franceptt.rb +6 -8
  127. data/lib/sisimai/rhost/godaddy.rb +12 -12
  128. data/lib/sisimai/rhost/{googleapps.rb → google.rb} +80 -72
  129. data/lib/sisimai/rhost/iua.rb +9 -10
  130. data/lib/sisimai/rhost/kddi.rb +6 -8
  131. data/lib/sisimai/rhost/{exchangeonline.rb → microsoft.rb} +115 -114
  132. data/lib/sisimai/rhost/mimecast.rb +42 -40
  133. data/lib/sisimai/rhost/nttdocomo.rb +12 -12
  134. data/lib/sisimai/rhost/spectrum.rb +10 -12
  135. data/lib/sisimai/rhost/{tencentqq.rb → tencent.rb} +7 -8
  136. data/lib/sisimai/rhost.rb +23 -31
  137. data/lib/sisimai/smtp/command.rb +59 -0
  138. data/lib/sisimai/smtp/error.rb +4 -7
  139. data/lib/sisimai/smtp/reply.rb +161 -74
  140. data/lib/sisimai/smtp/status.rb +504 -393
  141. data/lib/sisimai/smtp/transcript.rb +124 -0
  142. data/lib/sisimai/smtp.rb +0 -1
  143. data/lib/sisimai/string.rb +74 -5
  144. data/lib/sisimai/time.rb +1 -2
  145. data/lib/sisimai/version.rb +1 -1
  146. data/lib/sisimai.rb +35 -21
  147. data/set-of-emails/maildir/bsd/lhost-domino-02.eml +6 -3
  148. data/set-of-emails/maildir/bsd/lhost-googlegroups-15.eml +174 -0
  149. data/set-of-emails/maildir/bsd/lhost-gsuite-15.eml +229 -0
  150. data/set-of-emails/maildir/bsd/lhost-postfix-75.eml +51 -0
  151. data/set-of-emails/maildir/bsd/lhost-postfix-76.eml +101 -0
  152. data/set-of-emails/maildir/bsd/lhost-postfix-77.eml +74 -0
  153. data/set-of-emails/maildir/bsd/lhost-postfix-78.eml +91 -0
  154. data/set-of-emails/maildir/bsd/lhost-receivingses-08.eml +88 -0
  155. data/set-of-emails/maildir/bsd/rfc3464-43.eml +88 -0
  156. data/set-of-emails/maildir/bsd/rhost-google-03.eml +101 -0
  157. data/set-of-emails/maildir/bsd/rhost-google-04.eml +102 -0
  158. data/set-of-emails/maildir/bsd/rhost-google-05.eml +82 -0
  159. data/set-of-emails/maildir/bsd/rhost-google-06.eml +102 -0
  160. data/set-of-emails/maildir/bsd/rhost-google-07.eml +69 -0
  161. data/set-of-emails/maildir/bsd/rhost-google-08.eml +99 -0
  162. data/sisimai-java.gemspec +1 -1
  163. data/sisimai.gemspec +1 -1
  164. metadata +41 -20
  165. data/.rspec +0 -2
  166. data/lib/sisimai/data/yaml.rb +0 -33
  167. data/lib/sisimai/data.rb +0 -411
  168. data/lib/sisimai/mime.rb +0 -456
  169. /data/set-of-emails/maildir/bsd/{rfc3464-41.eml → rfc3834-05.eml} +0 -0
  170. /data/set-of-emails/maildir/bsd/{rhost-googleapps-01.eml → rhost-google-01.eml} +0 -0
  171. /data/set-of-emails/maildir/bsd/{rhost-googleapps-02.eml → rhost-google-02.eml} +0 -0
  172. /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-01.eml → rhost-microsoft-01.eml} +0 -0
  173. /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-02.eml → rhost-microsoft-02.eml} +0 -0
  174. /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-03.eml → rhost-microsoft-03.eml} +0 -0
  175. /data/set-of-emails/maildir/bsd/{rhost-tencentqq-01.eml → rhost-tencent-01.eml} +0 -0
  176. /data/set-of-emails/maildir/bsd/{rhost-tencentqq-02.eml → rhost-tencent-02.eml} +0 -0
  177. /data/set-of-emails/maildir/bsd/{rhost-tencentqq-03.eml → rhost-tencent-03.eml} +0 -0
@@ -1,13 +1,12 @@
1
1
  module Sisimai::Lhost
2
- # Sisimai::Lhost::Yandex parses a bounce email which created by Yandex.Mail.
3
- # Methods in the module are called from only Sisimai::Message.
2
+ # Sisimai::Lhost::Yandex parses a bounce email which created by Yandex.Mail. Methods in the module
3
+ # are called from only Sisimai::Message.
4
4
  module Yandex
5
5
  class << self
6
- # Imported from p5-Sisimail/lib/Sisimai/Lhost/Yandex.pm
7
6
  require 'sisimai/lhost'
8
7
 
9
8
  Indicators = Sisimai::Lhost.INDICATORS
10
- ReBackbone = %r|^Content-Type:[ ]message/rfc822|.freeze
9
+ Boundaries = ['Content-Type: message/rfc822'].freeze
11
10
  StartingOf = { message: ['This is the mail system at host yandex.ru.'] }.freeze
12
11
 
13
12
  # Parse bounce messages from Yandex.Mail
@@ -15,7 +14,7 @@ module Sisimai::Lhost
15
14
  # @param [String] mbody Message body of a bounce email
16
15
  # @return [Hash] Bounce data list and message/rfc822 part
17
16
  # @return [Nil] it failed to parse or the arguments are missing
18
- def make(mhead, mbody)
17
+ def inquire(mhead, mbody)
19
18
  # X-Yandex-Front: mxback1h.mail.yandex.net
20
19
  # X-Yandex-TimeMark: 1417885948
21
20
  # X-Yandex-Uniq: 92309766-f1c8-4bd4-92bc-657c75766587
@@ -26,13 +25,12 @@ module Sisimai::Lhost
26
25
  return nil unless mhead['x-yandex-uniq']
27
26
  return nil unless mhead['from'] == 'mailer-daemon@yandex.ru'
28
27
 
29
- require 'sisimai/rfc1894'
30
28
  fieldtable = Sisimai::RFC1894.FIELDTABLE
31
29
  permessage = {} # (Hash) Store values of each Per-Message field
32
30
 
33
31
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
34
- emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
35
- bodyslices = emailsteak[0].split("\n")
32
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
33
+ bodyslices = emailparts[0].split("\n")
36
34
  readslices = ['']
37
35
  readcursor = 0 # (Integer) Points the current cursor position
38
36
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
@@ -40,8 +38,8 @@ module Sisimai::Lhost
40
38
  v = nil
41
39
 
42
40
  while e = bodyslices.shift do
43
- # Read error messages and delivery status lines from the head of the email
44
- # to the previous line of the beginning of the original message.
41
+ # Read error messages and delivery status lines from the head of the email to the previous
42
+ # line of the beginning of the original message.
45
43
  readslices << e # Save the current line for the next loop
46
44
 
47
45
  if readcursor == 0
@@ -82,23 +80,21 @@ module Sisimai::Lhost
82
80
  next unless fieldtable[o[0]]
83
81
  v[fieldtable[o[0]]] = o[2]
84
82
 
85
- next unless f == 1
83
+ next unless f
86
84
  permessage[fieldtable[o[0]]] = o[2]
87
85
  end
88
86
  else
89
87
  # The line does not begin with a DSN field defined in RFC3464
90
- if cv = e.match(/[ \t][(]in reply to .*([A-Z]{4}).*/)
88
+ if e.include?(' (in reply to ') || e.include?('command)')
91
89
  # 5.1.1 <userunknown@example.co.jp>... User Unknown (in reply to RCPT TO
92
- commandset << cv[1]
90
+ cv = Sisimai::SMTP::Command.find(e)
91
+ commandset << cv if cv
93
92
 
94
- elsif cv = e.match(/([A-Z]{4})[ \t]*.*command[)]\z/)
95
- # to MAIL command)
96
- commandset << cv[1]
97
93
  else
98
94
  # Continued line of the value of Diagnostic-Code field
99
95
  next unless readslices[-2].start_with?('Diagnostic-Code:')
100
- next unless cv = e.match(/\A[ \t]+(.+)\z/)
101
- v['diagnosis'] << ' ' << cv[1]
96
+ next unless e.start_with?(' ')
97
+ v['diagnosis'] << ' ' << Sisimai::String.sweep(e)
102
98
  readslices[-1] = 'Diagnostic-Code: ' << e
103
99
  end
104
100
  end
@@ -110,11 +106,11 @@ module Sisimai::Lhost
110
106
  e['lhost'] ||= permessage['rhost']
111
107
  permessage.each_key { |a| e[a] ||= permessage[a] || '' }
112
108
 
113
- e['command'] = commandset.shift || ''
114
109
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].tr("\n", ' '))
110
+ e['command'] ||= commandset.shift || Sisimai::SMTP::Command.find(e['diagnosis']) || ''
115
111
  end
116
112
 
117
- return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
113
+ return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
118
114
  end
119
115
  def description; return 'Yandex.Mail: https://www.yandex.ru'; end
120
116
  end
@@ -1,13 +1,12 @@
1
1
  module Sisimai::Lhost
2
- # Sisimai::Lhost::Zoho parses a bounce email which created by Zoho Mail.
3
- # Methods in the module are called from only Sisimai::Message.
2
+ # Sisimai::Lhost::Zoho parses a bounce email which created by Zoho Mail. Methods in the module are
3
+ # called from only Sisimai::Message.
4
4
  module Zoho
5
5
  class << self
6
- # Imported from p5-Sisimail/lib/Sisimai/Lhost/Zoho.pm
7
6
  require 'sisimai/lhost'
8
7
 
9
8
  Indicators = Sisimai::Lhost.INDICATORS
10
- ReBackbone = %r|^Received:[ ]*from[ ]mail[.]zoho[.]com[ ]by[ ]mx[.]zohomail[.]com|.freeze
9
+ Boundaries = ['Received: from mail.zoho.com by mx.zohomail.com'].freeze
11
10
  StartingOf = { message: ['This message was created automatically by mail delivery'] }.freeze
12
11
  MessagesOf = { 'expired' => ['Host not reachable'] }.freeze
13
12
 
@@ -16,23 +15,23 @@ module Sisimai::Lhost
16
15
  # @param [String] mbody Message body of a bounce email
17
16
  # @return [Hash] Bounce data list and message/rfc822 part
18
17
  # @return [Nil] it failed to parse or the arguments are missing
19
- def make(mhead, mbody)
18
+ def inquire(mhead, mbody)
20
19
  # X-ZohoMail: Si CHF_MF_NL SS_10 UW48 UB48 FMWL UW48 UB48 SGR3_1_09124_42
21
20
  # X-Zoho-Virus-Status: 2
22
21
  # X-Mailer: Zoho Mail
23
22
  return nil unless mhead['x-zohomail']
24
23
 
25
24
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
26
- emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
27
- bodyslices = emailsteak[0].split("\n")
25
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
26
+ bodyslices = emailparts[0].split("\n")
28
27
  readcursor = 0 # (Integer) Points the current cursor position
29
28
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
30
29
  qprintable = false
31
30
  v = nil
32
31
 
33
32
  while e = bodyslices.shift do
34
- # Read error messages and delivery status lines from the head of the email
35
- # to the previous line of the beginning of the original message.
33
+ # Read error messages and delivery status lines from the head of the email to the previous
34
+ # line of the beginning of the original message.
36
35
  if readcursor == 0
37
36
  # Beginning of the bounce message or delivery status part
38
37
  readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
@@ -54,15 +53,15 @@ module Sisimai::Lhost
54
53
  # shironeko@example.org Invalid Address, ERROR_CODE :550, ERROR_CODE :Requested action not taken: mailbox unavailable
55
54
  v = dscontents[-1]
56
55
 
57
- if cv = e.match(/\A([^ ]+[@][^ ]+)[ \t]+(.+)\z/)
56
+ if Sisimai::String.aligned(e, ['@', ' ', 'ERROR_CODE :'])
58
57
  # kijitora@example.co.jp Invalid Address, ERROR_CODE :550, ERROR_CODE :5.1.=
59
58
  if v['recipient']
60
59
  # There are multiple recipient addresses in the message body.
61
60
  dscontents << Sisimai::Lhost.DELIVERYSTATUS
62
61
  v = dscontents[-1]
63
62
  end
64
- v['recipient'] = cv[1]
65
- v['diagnosis'] = cv[2]
63
+ v['recipient'] = e[0, e.index(' ')]
64
+ v['diagnosis'] = e[e.index(' ') + 1, e.size]
66
65
 
67
66
  if v['diagnosis'].end_with?('=')
68
67
  # Quoted printable
@@ -71,7 +70,7 @@ module Sisimai::Lhost
71
70
  end
72
71
  recipients += 1
73
72
 
74
- elsif cv = e.match(/\A\[Status: .+[<]([^ ]+[@][^ ]+)[>],/)
73
+ elsif e.start_with?('[Status: ')
75
74
  # Expired
76
75
  # [Status: Error, Address: <kijitora@6kaku.example.co.jp>, ResponseCode 421, , Host not reachable.]
77
76
  if v['recipient']
@@ -79,7 +78,9 @@ module Sisimai::Lhost
79
78
  dscontents << Sisimai::Lhost.DELIVERYSTATUS
80
79
  v = dscontents[-1]
81
80
  end
82
- v['recipient'] = cv[1]
81
+ p1 = e.index('<')
82
+ p2 = e.index('>', p1 + 2)
83
+ v['recipient'] = Sisimai::Address.s3s4(e[p1, p2 - p1])
83
84
  v['diagnosis'] = e
84
85
  recipients += 1
85
86
  else
@@ -100,7 +101,7 @@ module Sisimai::Lhost
100
101
  end
101
102
  end
102
103
 
103
- return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
104
+ return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
104
105
  end
105
106
  def description; return 'Zoho Mail: https://www.zoho.com'; end
106
107
  end
data/lib/sisimai/lhost.rb CHANGED
@@ -2,7 +2,6 @@ module Sisimai
2
2
  # Sisimai::Lhost - Base class for Sisimai::Lhost::*
3
3
  module Lhost
4
4
  class << self
5
- # Imported from p5-Sisimail/lib/Sisimai/Lhost.pm
6
5
  require 'sisimai/rfc5322'
7
6
 
8
7
  # Data structure for parsed bounce messages
@@ -23,7 +22,7 @@ module Sisimai
23
22
  'replycode' => nil, # SMTP Reply code
24
23
  'diagnosis' => nil, # The value of Diagnostic-Code header
25
24
  'recipient' => nil, # The value of Final-Recipient header
26
- 'softbounce' => nil, # Soft bounce or not
25
+ 'hardbounce' => nil, # Hard bounce or not
27
26
  'feedbacktype' => nil, # Feedback Type
28
27
  }
29
28
  end
@@ -42,13 +41,12 @@ module Sisimai
42
41
  # @return [Array] MTA list with order
43
42
  def index
44
43
  return %w[
45
- Activehunter Amavis AmazonSES AmazonWorkMail Aol ApacheJames Barracuda Bigfoot
46
- Biglobe Courier Domino EZweb EinsUndEins Exchange2003 Exchange2007 Exim FML
47
- Facebook GMX GSuite GoogleGroups Gmail IMailServer InterScanMSS KDDI MXLogic
48
- MailFoundry MailMarshalSMTP MailRu McAfee MessageLabs MessagingServer Notes
49
- Office365 OpenSMTPD Outlook Postfix PowerMTA ReceivingSES SendGrid Sendmail
50
- SurfControl V5sendmail Verizon X1 X2 X3 X4 X5 X6 Yahoo Yandex Zoho MFILTER
51
- Qmail
44
+ Activehunter Amavis AmazonSES AmazonWorkMail Aol ApacheJames Barracuda Bigfoot Biglobe
45
+ Courier Domino EZweb EinsUndEins Exchange2003 Exchange2007 Exim FML Facebook GMX GSuite
46
+ GoogleGroups Gmail IMailServer InterScanMSS KDDI MXLogic MailFoundry MailMarshalSMTP
47
+ MailRu McAfee MessageLabs MessagingServer Notes Office365 OpenSMTPD Outlook Postfix
48
+ PowerMTA ReceivingSES SendGrid Sendmail SurfControl V5sendmail Verizon X1 X2 X3 X4 X5 X6
49
+ Yahoo Yandex Zoho MFILTER Qmail
52
50
  ]
53
51
  end
54
52
 
@@ -71,7 +69,7 @@ module Sisimai
71
69
  # @param [String] mbody Message body of a bounce email
72
70
  # @return [Hash] Bounce data list and message/rfc822 part
73
71
  # @return [Nil] it failed to parse or the arguments are missing
74
- def make; return nil; end
72
+ def inquire; return nil; end
75
73
  def description; return ''; end
76
74
  end
77
75
  end
@@ -1,9 +1,7 @@
1
1
  module Sisimai
2
2
  class Mail
3
- # Sisimai::Mail::Maildir is a reader for getting contents of each email in
4
- # the Maildir/ directory.
3
+ # Sisimai::Mail::Maildir is a reader for getting contents of each email in the Maildir/ directory.
5
4
  class Maildir
6
- # Imported from p5-Sisimail/lib/Sisimai/Mail/Maildir.pm
7
5
  # :dir [String] Path to Maildir/
8
6
  # :size [Integer] The number of files/directories in the Maildir/
9
7
  # :path [String] Path to each file
@@ -2,7 +2,6 @@ module Sisimai
2
2
  class Mail
3
3
  # Sisimai::Mail::Mbox is a mailbox file (UNIX mbox) reader.
4
4
  class Mbox
5
- # Imported from p5-Sisimail/lib/Sisimai/Mail/Mbox.pm
6
5
  # :dir [String] Directory name of the mbox
7
6
  # :file [String] File name of the mbox
8
7
  # :path [String] Path to mbox
@@ -13,9 +12,9 @@ module Sisimai
13
12
  attr_accessor :offset, :handle
14
13
 
15
14
  # Constructor of Sisimai::Mail::Mbox
16
- # @param [String] argv1 Path to mbox
17
- # @return [Sisimai::Mail::Mbox,Nil] Object or nil if the argument is not
18
- # specified or does not exist
15
+ # @param [String] argv1 Path to mbox
16
+ # @return [Sisimai::Mail::Mbox] Object
17
+ # [Nil] is not specified or does not exist
19
18
  def initialize(argv1)
20
19
  raise Errno::ENOENT unless File.exist?(argv1)
21
20
  raise 'is not a file' unless File.ftype(argv1) == 'file'
@@ -2,7 +2,6 @@ module Sisimai
2
2
  class Mail
3
3
  # Sisimai::Mail::Memory is a class for reading an email string
4
4
  class Memory
5
- # Imported from p5-Sisimail/lib/Sisimai/Mail/Memory.pm
6
5
  # :path [String] Fixed string "<MEMORY>"
7
6
  # :size [Integer] data size of the email text
8
7
  # :payload [Array] Entire bounce mail message
@@ -1,9 +1,7 @@
1
1
  module Sisimai
2
2
  class Mail
3
- # Sisimai::Mail::STDIN is a reader for getting contents of each email from
4
- # STDIN
3
+ # Sisimai::Mail::STDIN is a reader for getting contents of each email from STDIN
5
4
  class STDIN
6
- # Imported from p5-Sisimail/lib/Sisimai/Mail/STDIN.pm
7
5
  # :path [String] Fixed string "<STDIN>"
8
6
  # :size [Integer] Data size which has been read
9
7
  # :offset [Integer] The number of emails which have neen read
data/lib/sisimai/mail.rb CHANGED
@@ -1,10 +1,7 @@
1
1
  module Sisimai
2
- # Sisimai::Mail is a handler of UNIX mbox or Maildir for reading each mail.
3
- # It is a wrapper class of Sisimai::Mail::Mbox, Sisimai::Mail::Maildir, and
4
- # Sisimai::Mail::Memory classes.
2
+ # Sisimai::Mail is a handler of UNIX mbox or Maildir for reading each mail. It is a wrapper class
3
+ # of Sisimai::Mail::Mbox, Sisimai::Mail::Maildir, and Sisimai::Mail::Memory classes.
5
4
  class Mail
6
- # Imported from p5-Sisimail/lib/Sisimai/Mail.pm
7
-
8
5
  # :path [String] path to mbox or Maildir/
9
6
  # :kind [String] Data type: mailbox, maildir, or stdin
10
7
  # :data [Sisimai::Mail::[Mbox,Maildir,Memory,STDIN]] Object
@@ -47,8 +44,7 @@ module Sisimai
47
44
  end
48
45
  end
49
46
  elsif argv1.is_a?(IO)
50
- # Read from STDIN
51
- # The argument neither a mailbox nor a Maildir/.
47
+ # Read from STDIN, The argument neither a mailbox nor a Maildir/.
52
48
  classname = self.class.to_s << '::STDIN'
53
49
  parameter['kind'] = 'stdin'
54
50
  parameter['path'] = '<STDIN>'
data/lib/sisimai/mda.rb CHANGED
@@ -1,25 +1,17 @@
1
1
  module Sisimai
2
2
  # Sisimai::MDA - Error message parser for MDA
3
3
  module MDA
4
- # Imported from p5-Sisimail/lib/Sisimai/MDA.pm
5
4
  class << self
6
5
  AgentNames = {
7
6
  # dovecot/src/deliver/deliver.c
8
7
  # 11: #define DEFAULT_MAIL_REJECTION_HUMAN_REASON \
9
8
  # 12: "Your message to <%t> was automatically rejected:%n%r"
10
- 'dovecot' => %r/\AYour message to [^ ]+ was automatically rejected:\z/,
11
- 'mail.local' => %r/\Amail[.]local: /,
12
- 'procmail' => %r/\Aprocmail: /,
13
- 'maildrop' => %r/\Amaildrop: /,
14
- 'vpopmail' => %r/\Avdelivermail: /,
15
- 'vmailmgr' => %r/\Avdeliver: /,
16
- }.freeze
17
- MarkingsOf = {
18
- message: %r{\A(?>
19
- Your[ ]message[ ]to[ ][^ ]+[ ]was[ ]automatically[ ]rejected:\z
20
- |(?:mail[.]local|procmail|maildrop|vdelivermail|vdeliver):[ ]
21
- )
22
- }x
9
+ 'dovecot' => ['Your message to ', ' was automatically rejected:'],
10
+ 'mail.local' => ['mail.local: '],
11
+ 'procmail' => ['procmail: '],
12
+ 'maildrop' => ['maildrop: '],
13
+ 'vpopmail' => ['vdelivermail: '],
14
+ 'vmailmgr' => ['vdeliver: '],
23
15
  }.freeze
24
16
 
25
17
  # dovecot/src/deliver/mail-send.c:94
@@ -79,43 +71,37 @@ module Sisimai
79
71
  # @param [String] mbody Message body of a bounce email
80
72
  # @return [Hash] Bounce data list and message/rfc822 part
81
73
  # @return [Nil] it failed to parse or the arguments are missing
82
- def make(mhead, mbody)
74
+ def inquire(mhead, mbody)
75
+ return nil unless mhead
76
+ return nil unless mbody.size > 0
83
77
  return nil unless mhead['from'].downcase.start_with?('mail delivery subsystem','mailer-daemon', 'postmaster')
84
78
 
85
- agentname0 = '' # [String] MDA name
79
+ deliversby = '' # [String] Mail Delivery Agent name
86
80
  reasonname = '' # [String] Error reason
87
81
  bouncemesg = '' # [String] Error message
88
- bodyslices = mbody.split("\n")
89
- linebuffer = []
82
+ linebuffer = mbody.split("\n")
90
83
 
91
- while e = bodyslices.shift do
92
- # Check each line with each MDA's symbol regular expression.
93
- if agentname0 == ''
94
- # Try to match with each regular expression
95
- next if e.empty?
96
- next unless e =~ MarkingsOf[:message]
84
+ AgentNames.each_key do |e|
85
+ # Find a mail delivery agent name from the entire message body
86
+ p = mbody.index(AgentNames[e][0])
87
+ next unless p
97
88
 
98
- AgentNames.each_key do |f|
99
- # Detect the agent name from the line
100
- next unless e =~ AgentNames[f]
101
- agentname0 = f
102
- break
103
- end
89
+ if AgentNames[e].size > 1
90
+ # Try to find the 2nd argument
91
+ q = mbody.index(AgentNames[e][1])
92
+ next unless q
93
+ next if p > q
104
94
  end
105
-
106
- # Append error message lines to @linebuffer
107
- linebuffer << e
108
- break if e.empty?
95
+ deliversby = e
96
+ break
109
97
  end
110
- return nil if agentname0.empty?
111
- return nil if linebuffer.empty?
98
+ return nil if deliversby.empty?
112
99
 
113
- MessagesOf[agentname0].each_key do |e|
100
+ MessagesOf[deliversby].each_key do |e|
114
101
  # Detect an error reason from message patterns of the MDA.
115
- duplicated = linebuffer.dup
116
- while f = duplicated.shift do
117
- # Whether the error message include each message defined in $MessagesOf
118
- next unless MessagesOf[agentname0][e].any? { |a| f.downcase.include?(a) }
102
+ linebuffer.each do |f|
103
+ # Whether the error message include each message defined in MessagesOf
104
+ next unless MessagesOf[deliversby][e].any? { |a| f.downcase.include?(a) }
119
105
  reasonname = e
120
106
  bouncemesg = f
121
107
  break
@@ -124,7 +110,7 @@ module Sisimai
124
110
  end
125
111
 
126
112
  return {
127
- 'mda' => agentname0,
113
+ 'mda' => deliversby,
128
114
  'reason' => reasonname || '',
129
115
  'message' => bouncemesg || '',
130
116
  }