sisimai 4.24.1-java → 4.25.0-java

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 (155) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -2
  3. data/ANALYTICAL-PRECISION +16 -25
  4. data/ChangeLog.md +41 -0
  5. data/Developers.mk +2 -2
  6. data/README-JA.md +13 -13
  7. data/README.md +13 -13
  8. data/lib/sisimai.rb +3 -7
  9. data/lib/sisimai/address.rb +25 -41
  10. data/lib/sisimai/arf.rb +58 -59
  11. data/lib/sisimai/bite.rb +0 -1
  12. data/lib/sisimai/bite/email.rb +7 -7
  13. data/lib/sisimai/bite/email/activehunter.rb +4 -3
  14. data/lib/sisimai/bite/email/amavis.rb +133 -0
  15. data/lib/sisimai/bite/email/amazonses.rb +53 -87
  16. data/lib/sisimai/bite/email/amazonworkmail.rb +51 -57
  17. data/lib/sisimai/bite/email/aol.rb +50 -76
  18. data/lib/sisimai/bite/email/apachejames.rb +2 -2
  19. data/lib/sisimai/bite/email/bigfoot.rb +47 -74
  20. data/lib/sisimai/bite/email/biglobe.rb +8 -9
  21. data/lib/sisimai/bite/email/courier.rb +56 -101
  22. data/lib/sisimai/bite/email/domino.rb +7 -8
  23. data/lib/sisimai/bite/email/einsundeins.rb +4 -5
  24. data/lib/sisimai/bite/email/exchange2003.rb +21 -22
  25. data/lib/sisimai/bite/email/exchange2007.rb +26 -28
  26. data/lib/sisimai/bite/email/exim.rb +48 -47
  27. data/lib/sisimai/bite/email/ezweb.rb +24 -36
  28. data/lib/sisimai/bite/email/facebook.rb +54 -79
  29. data/lib/sisimai/bite/email/fml.rb +10 -10
  30. data/lib/sisimai/bite/email/gmx.rb +6 -6
  31. data/lib/sisimai/bite/email/google.rb +12 -13
  32. data/lib/sisimai/bite/email/gsuite.rb +80 -108
  33. data/lib/sisimai/bite/email/imailserver.rb +16 -16
  34. data/lib/sisimai/bite/email/interscanmss.rb +4 -6
  35. data/lib/sisimai/bite/email/kddi.rb +9 -11
  36. data/lib/sisimai/bite/email/mailfoundry.rb +2 -2
  37. data/lib/sisimai/bite/email/mailmarshalsmtp.rb +2 -2
  38. data/lib/sisimai/bite/email/mailru.rb +12 -13
  39. data/lib/sisimai/bite/email/mcafee.rb +31 -25
  40. data/lib/sisimai/bite/email/messagelabs.rb +48 -87
  41. data/lib/sisimai/bite/email/messagingserver.rb +9 -10
  42. data/lib/sisimai/bite/email/mfilter.rb +16 -16
  43. data/lib/sisimai/bite/email/mxlogic.rb +11 -11
  44. data/lib/sisimai/bite/email/notes.rb +5 -6
  45. data/lib/sisimai/bite/email/office365.rb +25 -42
  46. data/lib/sisimai/bite/email/opensmtpd.rb +8 -8
  47. data/lib/sisimai/bite/email/outlook.rb +49 -67
  48. data/lib/sisimai/bite/email/postfix.rb +78 -112
  49. data/lib/sisimai/bite/email/qmail.rb +23 -23
  50. data/lib/sisimai/bite/email/receivingses.rb +53 -86
  51. data/lib/sisimai/bite/email/sendgrid.rb +65 -84
  52. data/lib/sisimai/bite/email/sendmail.rb +89 -117
  53. data/lib/sisimai/bite/email/surfcontrol.rb +15 -18
  54. data/lib/sisimai/bite/email/userdefined.rb +1 -1
  55. data/lib/sisimai/bite/email/v5sendmail.rb +3 -4
  56. data/lib/sisimai/bite/email/verizon.rb +7 -8
  57. data/lib/sisimai/bite/email/x1.rb +2 -2
  58. data/lib/sisimai/bite/email/x2.rb +2 -2
  59. data/lib/sisimai/bite/email/x3.rb +3 -3
  60. data/lib/sisimai/bite/email/x4.rb +22 -22
  61. data/lib/sisimai/bite/email/x5.rb +40 -49
  62. data/lib/sisimai/bite/email/yahoo.rb +3 -3
  63. data/lib/sisimai/bite/email/yandex.rb +54 -82
  64. data/lib/sisimai/bite/email/zoho.rb +6 -6
  65. data/lib/sisimai/bite/json/amazonses.rb +20 -20
  66. data/lib/sisimai/bite/json/sendgrid.rb +2 -2
  67. data/lib/sisimai/data.rb +27 -40
  68. data/lib/sisimai/datetime.rb +146 -162
  69. data/lib/sisimai/mda.rb +30 -31
  70. data/lib/sisimai/message/email.rb +83 -123
  71. data/lib/sisimai/message/json.rb +2 -4
  72. data/lib/sisimai/mime.rb +31 -34
  73. data/lib/sisimai/order/email.rb +23 -22
  74. data/lib/sisimai/reason.rb +61 -61
  75. data/lib/sisimai/reason/blocked.rb +139 -135
  76. data/lib/sisimai/reason/contenterror.rb +11 -10
  77. data/lib/sisimai/reason/exceedlimit.rb +4 -4
  78. data/lib/sisimai/reason/expired.rb +20 -20
  79. data/lib/sisimai/reason/filtered.rb +19 -18
  80. data/lib/sisimai/reason/hasmoved.rb +3 -3
  81. data/lib/sisimai/reason/hostunknown.rb +19 -19
  82. data/lib/sisimai/reason/mailboxfull.rb +49 -49
  83. data/lib/sisimai/reason/mailererror.rb +16 -16
  84. data/lib/sisimai/reason/mesgtoobig.rb +17 -17
  85. data/lib/sisimai/reason/networkerror.rb +19 -19
  86. data/lib/sisimai/reason/norelaying.rb +16 -16
  87. data/lib/sisimai/reason/notaccept.rb +9 -10
  88. data/lib/sisimai/reason/onhold.rb +1 -1
  89. data/lib/sisimai/reason/policyviolation.rb +21 -20
  90. data/lib/sisimai/reason/rejected.rb +53 -53
  91. data/lib/sisimai/reason/securityerror.rb +29 -29
  92. data/lib/sisimai/reason/spamdetected.rb +127 -127
  93. data/lib/sisimai/reason/suspend.rb +17 -17
  94. data/lib/sisimai/reason/systemerror.rb +22 -21
  95. data/lib/sisimai/reason/systemfull.rb +6 -6
  96. data/lib/sisimai/reason/toomanyconn.rb +19 -18
  97. data/lib/sisimai/reason/userunknown.rb +122 -121
  98. data/lib/sisimai/reason/vacation.rb +8 -8
  99. data/lib/sisimai/reason/virusdetected.rb +8 -8
  100. data/lib/sisimai/rfc1894.rb +142 -0
  101. data/lib/sisimai/rfc3464.rb +70 -70
  102. data/lib/sisimai/rfc3834.rb +15 -15
  103. data/lib/sisimai/rfc5322.rb +20 -36
  104. data/lib/sisimai/rhost.rb +1 -0
  105. data/lib/sisimai/rhost/exchangeonline.rb +31 -33
  106. data/lib/sisimai/rhost/franceptt.rb +23 -23
  107. data/lib/sisimai/rhost/godaddy.rb +28 -28
  108. data/lib/sisimai/rhost/googleapps.rb +39 -41
  109. data/lib/sisimai/rhost/kddi.rb +3 -3
  110. data/lib/sisimai/rhost/tencentqq.rb +51 -0
  111. data/lib/sisimai/smtp/error.rb +14 -21
  112. data/lib/sisimai/smtp/reply.rb +14 -13
  113. data/lib/sisimai/smtp/status.rb +178 -179
  114. data/lib/sisimai/string.rb +13 -12
  115. data/lib/sisimai/version.rb +1 -1
  116. data/set-of-emails/README.md +1 -5
  117. data/set-of-emails/maildir/bsd/arf-23.eml +49 -0
  118. data/set-of-emails/maildir/bsd/email-amavis-01.eml +78 -0
  119. data/set-of-emails/maildir/bsd/email-amavis-02.eml +78 -0
  120. data/set-of-emails/maildir/bsd/email-exchange2007-04.eml +146 -0
  121. data/set-of-emails/maildir/bsd/email-exim-60.eml +94 -0
  122. data/set-of-emails/maildir/bsd/email-ezweb-08.eml +49 -0
  123. data/set-of-emails/maildir/bsd/email-google-19.eml +67 -0
  124. data/set-of-emails/maildir/bsd/email-mcafee-05.eml +74 -0
  125. data/set-of-emails/maildir/bsd/email-messagingserver-12.eml +99 -0
  126. data/set-of-emails/maildir/bsd/email-postfix-46.eml +81 -0
  127. data/set-of-emails/maildir/bsd/email-postfix-47.eml +79 -0
  128. data/set-of-emails/maildir/bsd/email-postfix-48.eml +79 -0
  129. data/set-of-emails/maildir/bsd/email-postfix-49.eml +141 -0
  130. data/set-of-emails/maildir/bsd/email-postfix-50.eml +143 -0
  131. data/set-of-emails/maildir/bsd/email-postfix-51.eml +73 -0
  132. data/set-of-emails/maildir/bsd/email-postfix-52.eml +79 -0
  133. data/set-of-emails/maildir/bsd/email-postfix-53.eml +76 -0
  134. data/set-of-emails/maildir/bsd/email-postfix-54.eml +73 -0
  135. data/set-of-emails/maildir/bsd/email-postfix-55.eml +74 -0
  136. data/set-of-emails/maildir/bsd/email-postfix-56.eml +78 -0
  137. data/set-of-emails/maildir/bsd/email-qmail-10.eml +50 -0
  138. data/set-of-emails/maildir/bsd/email-x2-05.eml +38 -0
  139. data/set-of-emails/maildir/bsd/rhost-google-apps-02.eml +88 -0
  140. data/set-of-emails/maildir/bsd/rhost-tencentqq-01.eml +84 -0
  141. data/set-of-emails/maildir/bsd/rhost-tencentqq-02.eml +84 -0
  142. data/set-of-emails/maildir/bsd/rhost-tencentqq-03.eml +81 -0
  143. data/set-of-emails/maildir/dos/email-amavis-01.eml +78 -0
  144. data/set-of-emails/maildir/dos/email-apachejames-01.eml +1 -2
  145. data/set-of-emails/maildir/dos/email-messagelabs-01.eml +67 -50
  146. data/set-of-emails/maildir/dos/email-x4-01.eml +31 -76
  147. data/set-of-emails/maildir/dos/rhost-tencentqq-01.eml +84 -0
  148. data/set-of-emails/maildir/mac/email-amavis-01.eml +1 -4
  149. data/set-of-emails/maildir/mac/email-apachejames-01.eml +1 -9
  150. data/set-of-emails/maildir/mac/email-messagelabs-01.eml +1 -9
  151. data/set-of-emails/maildir/mac/email-x4-01.eml +1 -5
  152. data/set-of-emails/maildir/mac/rhost-tencentqq-01.eml +1 -4
  153. metadata +35 -4
  154. data/set-of-emails/logo/horizontalversions.png +0 -0
  155. data/set-of-emails/logo/icon.png +0 -0
@@ -16,9 +16,9 @@ module Sisimai::Bite::Email
16
16
  /x,
17
17
  }.freeze
18
18
  MessagesOf = {
19
- mailboxfull: ['As their mailbox is full'],
20
- norelaying: ['Due to the following SMTP relay error'],
21
- hostunknown: ['As the remote domain doesnt exist'],
19
+ 'mailboxfull' => ['As their mailbox is full'],
20
+ 'norelaying' => ['Due to the following SMTP relay error'],
21
+ 'hostunknown' => ['As the remote domain doesnt exist'],
22
22
  }.freeze
23
23
 
24
24
  def description; return 'au by KDDI: http://www.au.kddi.com'; end
@@ -71,7 +71,7 @@ module Sisimai::Bite::Email
71
71
  end
72
72
 
73
73
  if readcursor & Indicators[:'message-rfc822'] > 0
74
- # After "message/rfc822"
74
+ # Inside of the original message part
75
75
  if e.empty?
76
76
  blanklines += 1
77
77
  break if blanklines > 1
@@ -79,7 +79,7 @@ module Sisimai::Bite::Email
79
79
  end
80
80
  rfc822list << e
81
81
  else
82
- # Before "message/rfc822"
82
+ # Error message part
83
83
  next if (readcursor & Indicators[:deliverystatus]) == 0
84
84
  next if e.empty?
85
85
 
@@ -93,12 +93,10 @@ module Sisimai::Bite::Email
93
93
  dscontents << Sisimai::Bite.DELIVERYSTATUS
94
94
  v = dscontents[-1]
95
95
  end
96
-
97
96
  r = Sisimai::Address.s3s4(cv[1])
98
- if Sisimai::RFC5322.is_emailaddress(r)
99
- v['recipient'] = r
100
- recipients += 1
101
- end
97
+ next unless Sisimai::RFC5322.is_emailaddress(r)
98
+ v['recipient'] = r
99
+ recipients += 1
102
100
 
103
101
  elsif cv = e.match(/Your mail sent on: (.+)\z/)
104
102
  # Your mail sent on: Thu, 29 Apr 2010 11:04:47 +0900
@@ -130,7 +128,7 @@ module Sisimai::Bite::Email
130
128
  MessagesOf.each_key do |r|
131
129
  # Verify each regular expression of session errors
132
130
  next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
133
- e['reason'] = r.to_s
131
+ e['reason'] = r
134
132
  break
135
133
  end
136
134
  end
@@ -58,7 +58,7 @@ module Sisimai::Bite::Email
58
58
  end
59
59
 
60
60
  if readcursor & Indicators[:'message-rfc822'] > 0
61
- # After "message/rfc822"
61
+ # Inside of the original message part
62
62
  if e.empty?
63
63
  blanklines += 1
64
64
  break if blanklines > 1
@@ -66,7 +66,7 @@ module Sisimai::Bite::Email
66
66
  end
67
67
  rfc822list << e
68
68
  else
69
- # Before "message/rfc822"
69
+ # Error message part
70
70
  next if (readcursor & Indicators[:deliverystatus]) == 0
71
71
  next if e.empty?
72
72
 
@@ -68,7 +68,7 @@ module Sisimai::Bite::Email
68
68
  end
69
69
 
70
70
  if readcursor & Indicators[:'message-rfc822'] > 0
71
- # After "message/rfc822"
71
+ # Inside of the original message part
72
72
  if e.empty?
73
73
  blanklines += 1
74
74
  break if blanklines > 1
@@ -76,7 +76,7 @@ module Sisimai::Bite::Email
76
76
  end
77
77
  rfc822list << e
78
78
  else
79
- # Before "message/rfc822"
79
+ # Error message part
80
80
  next if (readcursor & Indicators[:deliverystatus]) == 0
81
81
  break if e =~ regularexp
82
82
 
@@ -18,39 +18,39 @@ module Sisimai::Bite::Email
18
18
  %r/SMTP error from remote (?:mail server|mailer) after end of ([A-Za-z]{4})/,
19
19
  ].freeze
20
20
  MessagesOf = {
21
- expired: [
21
+ 'expired' => [
22
22
  'retry timeout exceeded',
23
23
  'No action is required on your part',
24
24
  ],
25
- userunknown: ['user not found'],
26
- hostunknown: [
25
+ 'userunknown' => ['user not found'],
26
+ 'hostunknown' => [
27
27
  'all host address lookups failed permanently',
28
28
  'all relevant MX records point to non-existent hosts',
29
29
  'Unrouteable address',
30
30
  ],
31
- mailboxfull: ['mailbox is full', 'error: quota exceed'],
32
- notaccept: [
31
+ 'mailboxfull' => ['mailbox is full', 'error: quota exceed'],
32
+ 'notaccept' => [
33
33
  'an MX or SRV record indicated no SMTP service',
34
34
  'no host found for existing SMTP connection',
35
35
  ],
36
- syntaxerror: [
36
+ 'syntaxerror' => [
37
37
  'angle-brackets nested too deep',
38
38
  'expected word or "<"',
39
39
  'domain missing in source-routed address',
40
40
  'malformed address:',
41
41
  ],
42
- systemerror: [
42
+ 'systemerror' => [
43
43
  'delivery to file forbidden',
44
44
  'delivery to pipe forbidden',
45
45
  'local delivery failed',
46
46
  'LMTP error after ',
47
47
  ],
48
- contenterror: ['Too many "Received" headers'],
48
+ 'contenterror' => ['Too many "Received" headers'],
49
49
  }.freeze
50
50
 
51
51
  def description; return '@mail.ru: https://mail.ru'; end
52
52
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
53
- def headerlist; return ['X-Failed-Recipients']; end
53
+ def headerlist; return %w[x-failed-recipients]; end
54
54
 
55
55
  # Parse bounce messages from @mail.ru
56
56
  # @param [Hash] mhead Message headers of a bounce email
@@ -103,8 +103,7 @@ module Sisimai::Bite::Email
103
103
  end
104
104
 
105
105
  if readcursor & Indicators[:'message-rfc822'] > 0
106
- # After "message/rfc822"
107
- # After "message/rfc822"
106
+ # Inside of the original message part
108
107
  if e.empty?
109
108
  blanklines += 1
110
109
  break if blanklines > 1
@@ -112,7 +111,7 @@ module Sisimai::Bite::Email
112
111
  end
113
112
  rfc822list << e
114
113
  else
115
- # Before "message/rfc822"
114
+ # Error message part
116
115
  next if (readcursor & Indicators[:deliverystatus]) == 0
117
116
  next if e.empty?
118
117
 
@@ -235,7 +234,7 @@ module Sisimai::Bite::Email
235
234
  MessagesOf.each_key do |r|
236
235
  # Check each regular expression
237
236
  next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
238
- e['reason'] = r.to_s
237
+ e['reason'] = r
239
238
  break
240
239
  end
241
240
  end
@@ -12,12 +12,18 @@ module Sisimai::Bite::Email
12
12
  rfc822: ['Content-Type: message/rfc822'],
13
13
  }.freeze
14
14
  ReFailures = {
15
- userunknown: %r/(?:User [(].+[@].+[)] unknown[.]|550 Unknown user [^ ]+[@][^ ]+)/,
15
+ 'userunknown' => %r{(?:
16
+ [ ]User[ ][(].+[@].+[)][ ]unknown[.][ ]
17
+ |550[ ]Unknown[ ]user[ ][^ ]+[@][^ ]+
18
+ |550[ ][<].+?[@].+?[>][.]+[ ]User[ ]not[ ]exist
19
+ |No[ ]such[ ]user
20
+ )
21
+ }x,
16
22
  }.freeze
17
23
 
18
24
  def description; return 'McAfee Email Appliance'; end
19
25
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
20
- def headerlist; return ['X-NAI-Header']; end
26
+ def headerlist; return %w[x-nai-header]; end
21
27
 
22
28
  # Parse bounce messages from McAfee Email Appliance
23
29
  # @param [Hash] mhead Message headers of a bounce email
@@ -35,6 +41,8 @@ module Sisimai::Bite::Email
35
41
  return nil unless mhead['x-nai-header'].start_with?('Modified by McAfee ')
36
42
  return nil unless mhead['subject'] == 'Delivery Status'
37
43
 
44
+ require 'sisimai/rfc1894'
45
+ fieldtable = Sisimai::RFC1894.FIELDTABLE
38
46
  dscontents = [Sisimai::Bite.DELIVERYSTATUS]
39
47
  hasdivided = mbody.split("\n")
40
48
  havepassed = ['']
@@ -67,7 +75,7 @@ module Sisimai::Bite::Email
67
75
  end
68
76
 
69
77
  if readcursor & Indicators[:'message-rfc822'] > 0
70
- # After "message/rfc822"
78
+ # Inside of the original message part
71
79
  if e.empty?
72
80
  blanklines += 1
73
81
  break if blanklines > 1
@@ -75,7 +83,7 @@ module Sisimai::Bite::Email
75
83
  end
76
84
  rfc822list << e
77
85
  else
78
- # Before "message/rfc822"
86
+ # Error message part
79
87
  next if (readcursor & Indicators[:deliverystatus]) == 0
80
88
  next if e.empty?
81
89
 
@@ -101,28 +109,26 @@ module Sisimai::Bite::Email
101
109
  diagnostic = cv[2]
102
110
  recipients += 1
103
111
 
104
- elsif cv = e.match(/\AOriginal-Recipient:[ ]*([^ ]+)\z/)
105
- # Original-Recipient: <kijitora@example.co.jp>
106
- v['alias'] = Sisimai::Address.s3s4(cv[1])
107
-
108
- elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
109
- # Action: failed
110
- v['action'] = cv[1].downcase
112
+ elsif f = Sisimai::RFC1894.match(e)
113
+ # "e" matched with any field defined in RFC3464
114
+ o = Sisimai::RFC1894.field(e)
115
+ unless o
116
+ # Fallback code for empty value or invalid formatted value
117
+ # - Original-Recipient: <kijitora@example.co.jp>
118
+ if cv = e.match(/\AOriginal-Recipient:[ ]*([^ ]+)\z/)
119
+ v['alias'] = Sisimai::Address.s3s4(cv[1])
120
+ end
121
+ next
122
+ end
123
+ next unless fieldtable.key?(o[0])
124
+ v[fieldtable[o[0]]] = o[2]
111
125
 
112
- elsif cv = e.match(/\ARemote-MTA:[ ]*(.+)\z/)
113
- # Remote-MTA: 192.0.2.192
114
- v['rhost'] = cv[1].downcase
115
126
  else
116
- if cv = e.match(/\ADiagnostic-Code:[ ]*(.+?);[ ]*(.+)\z/)
117
- # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
118
- v['spec'] = cv[1].upcase
119
- v['diagnosis'] = cv[2]
120
-
121
- elsif p.start_with?('Diagnostic-Code:') && cv = e.match(/\A[ \t]+(.+)\z/)
122
- # Continued line of the value of Diagnostic-Code header
123
- v['diagnosis'] << ' ' << cv[1]
124
- havepassed[-1] = 'Diagnostic-Code: ' << e
125
- end
127
+ # Continued line of the value of Diagnostic-Code field
128
+ next unless p.start_with?('Diagnostic-Code:')
129
+ next unless cv = e.match(/\A[ \t]+(.+)\z/)
130
+ v['diagnosis'] << ' ' << cv[1]
131
+ havepassed[-1] = 'Diagnostic-Code: ' << e
126
132
  end
127
133
  end
128
134
  end
@@ -135,7 +141,7 @@ module Sisimai::Bite::Email
135
141
  ReFailures.each_key do |r|
136
142
  # Verify each regular expression of session errors
137
143
  next unless e['diagnosis'] =~ ReFailures[r]
138
- e['reason'] = r.to_s
144
+ e['reason'] = r
139
145
  break
140
146
  end
141
147
  e.each_key { |a| e[a] ||= '' }
@@ -13,8 +13,8 @@ module Sisimai::Bite::Email
13
13
  rfc822: ['Content-Type: text/rfc822-headers'],
14
14
  }.freeze
15
15
  ReFailures = {
16
- userunknown: %r/(?:542 .+ Rejected|No such user)/,
17
- securityerror: %r/Please turn on SMTP Authentication in your mail client/,
16
+ 'userunknown' => %r/(?:542 .+ Rejected|No such user)/,
17
+ 'securityerror' => %r/Please turn on SMTP Authentication in your mail client/,
18
18
  }.freeze
19
19
 
20
20
  def description; return 'Symantec.cloud http://www.messagelabs.com'; end
@@ -25,7 +25,7 @@ module Sisimai::Bite::Email
25
25
  # X-StarScan-Received:
26
26
  # X-StarScan-Version: 6.12.5; banners=-,-,-
27
27
  # X-VirusChecked: Checked
28
- def headerlist; return ['X-Msg-Ref']; end
28
+ def headerlist; return %w[x-msg-ref]; end
29
29
 
30
30
  # Parse bounce messages from Symantec.cloud(MessageLabs)
31
31
  # @param [Hash] mhead Message headers of a bounce email
@@ -43,6 +43,10 @@ module Sisimai::Bite::Email
43
43
  return nil unless mhead['from'].include?('MAILER-DAEMON@messagelabs.com')
44
44
  return nil unless mhead['subject'].start_with?('Mail Delivery Failure')
45
45
 
46
+ require 'sisimai/rfc1894'
47
+ fieldtable = Sisimai::RFC1894.FIELDTABLE
48
+ permessage = {} # (Hash) Store values of each Per-Message field
49
+
46
50
  dscontents = [Sisimai::Bite.DELIVERYSTATUS]
47
51
  hasdivided = mbody.split("\n")
48
52
  havepassed = ['']
@@ -51,11 +55,6 @@ module Sisimai::Bite::Email
51
55
  readcursor = 0 # (Integer) Points the current cursor position
52
56
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
53
57
  commandset = [] # (Array) ``in reply to * command'' list
54
- connvalues = 0 # (Integer) Flag, 1 if all the value of connheader have been set
55
- connheader = {
56
- 'date' => '', # The value of Arrival-Date header
57
- 'lhost' => '', # The value of Reporting-MTA header
58
- }
59
58
  v = nil
60
59
 
61
60
  while e = hasdivided.shift do
@@ -64,7 +63,7 @@ module Sisimai::Bite::Email
64
63
  p = havepassed[-2]
65
64
 
66
65
  if readcursor == 0
67
- # Beginning of the bounce message or delivery status part
66
+ # Beginning of the bounce message or message/delivery-status part
68
67
  if e.start_with?(StartingOf[:message][0])
69
68
  readcursor |= Indicators[:deliverystatus]
70
69
  next
@@ -72,7 +71,7 @@ module Sisimai::Bite::Email
72
71
  end
73
72
 
74
73
  if (readcursor & Indicators[:'message-rfc822']) == 0
75
- # Beginning of the original message part
74
+ # Beginning of the original message part(message/rfc822)
76
75
  if e == StartingOf[:rfc822][0]
77
76
  readcursor |= Indicators[:'message-rfc822']
78
77
  next
@@ -80,7 +79,7 @@ module Sisimai::Bite::Email
80
79
  end
81
80
 
82
81
  if readcursor & Indicators[:'message-rfc822'] > 0
83
- # After "message/rfc822"
82
+ # message/rfc822 OR text/rfc822-headers part
84
83
  if e.empty?
85
84
  blanklines += 1
86
85
  break if blanklines > 1
@@ -88,96 +87,58 @@ module Sisimai::Bite::Email
88
87
  end
89
88
  rfc822list << e
90
89
  else
91
- # Before "message/rfc822"
90
+ # message/delivery-status part
92
91
  next if (readcursor & Indicators[:deliverystatus]) == 0
93
92
  next if e.empty?
94
93
 
95
- if connvalues == connheader.keys.size
96
- # This is the mail delivery agent at messagelabs.com.
97
- #
98
- # I was unable to deliver your message to the following addresses:
99
- #
100
- # maria@dest.example.net
101
- #
102
- # Reason: 550 maria@dest.example.net... No such user
103
- #
104
- # The message subject was: Re: BOAS FESTAS!
105
- # The message date was: Tue, 23 Dec 2014 20:39:24 +0000
106
- # The message identifier was: DB/3F-17375-60D39495
107
- # The message reference was: server-5.tower-143.messagelabs.com!1419367172!32=
108
- # 691968!1
109
- #
110
- # Please do not reply to this email as it is sent from an unattended mailbox.
111
- # Please visit www.messagelabs.com/support for more details
112
- # about this error message and instructions to resolve this issue.
113
- #
114
- #
115
- # --b0Nvs+XKfKLLRaP/Qo8jZhQPoiqeWi3KWPXMgw==
116
- # Content-Type: message/delivery-status
117
- #
118
- # Reporting-MTA: dns; server-15.bemta-3.messagelabs.com
119
- # Arrival-Date: Tue, 23 Dec 2014 20:39:34 +0000
120
- #
121
- # Action: failed
122
- # Status: 5.0.0
123
- # Last-Attempt-Date: Tue, 23 Dec 2014 20:39:35 +0000
124
- # Remote-MTA: dns; mail.dest.example.net
125
- # Diagnostic-Code: smtp; 550 maria@dest.example.net... No such user
126
- # Final-Recipient: rfc822; maria@dest.example.net
94
+ if f = Sisimai::RFC1894.match(e)
95
+ # "e" matched with any field defined in RFC3464
96
+ next unless o = Sisimai::RFC1894.field(e)
127
97
  v = dscontents[-1]
128
98
 
129
- if cv = e.match(/\AFinal-Recipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/)
130
- # Final-Recipient: rfc822; maria@dest.example.net
131
- if v['recipient']
132
- # There are multiple recipient addresses in the message body.
133
- dscontents << Sisimai::Bite.DELIVERYSTATUS
134
- v = dscontents[-1]
99
+ if o[-1] == 'addr'
100
+ # Final-Recipient: rfc822; kijitora@example.jp
101
+ # X-Actual-Recipient: rfc822; kijitora@example.co.jp
102
+ if o[0] == 'final-recipient'
103
+ # Final-Recipient: rfc822; kijitora@example.jp
104
+ if v['recipient']
105
+ # There are multiple recipient addresses in the message body.
106
+ dscontents << Sisimai::Bite.DELIVERYSTATUS
107
+ v = dscontents[-1]
108
+ end
109
+ v['recipient'] = o[2]
110
+ recipients += 1
111
+ else
112
+ # X-Actual-Recipient: rfc822; kijitora@example.co.jp
113
+ v['alias'] = o[2]
135
114
  end
136
- v['recipient'] = cv[1]
137
- recipients += 1
138
-
139
- elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
140
- # Action: failed
141
- v['action'] = cv[1].downcase
142
-
143
- elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
144
- # Status: 5.0.0
145
- v['status'] = cv[1]
115
+ elsif o[-1] == 'code'
116
+ # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
117
+ v['spec'] = o[1]
118
+ v['diagnosis'] = o[2]
146
119
  else
147
- if cv = e.match(/\ADiagnostic-Code:[ ]*(.+?);[ ]*(.+)\z/)
148
- # Diagnostic-Code: smtp; 550 maria@dest.example.net... No such user
149
- v['spec'] = cv[1].upcase
150
- v['diagnosis'] = cv[2]
151
-
152
- elsif p.start_with?('Diagnostic-Code:') && cv = e.match(/\A[ \t]+(.+)\z/)
153
- # Continued line of the value of Diagnostic-Code header
154
- v['diagnosis'] << ' ' << cv[1]
155
- havepassed[-1] = 'Diagnostic-Code: ' << e
156
- end
120
+ # Other DSN fields defined in RFC3464
121
+ next unless fieldtable.key?(o[0])
122
+ v[fieldtable[o[0]]] = o[2]
123
+
124
+ next unless f == 1
125
+ permessage[fieldtable[o[0]]] = o[2]
157
126
  end
158
127
  else
159
- # Reporting-MTA: dns; server-15.bemta-3.messagelabs.com
160
- # Arrival-Date: Tue, 23 Dec 2014 20:39:34 +0000
161
- if cv = e.match(/\AReporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
162
- # Reporting-MTA: dns; server-15.bemta-3.messagelabs.com
163
- next unless connheader['lhost'].empty?
164
- connheader['lhost'] = cv[1].downcase
165
- connvalues += 1
166
-
167
- elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/)
168
- # Arrival-Date: Tue, 23 Dec 2014 20:39:34 +0000
169
- next unless connheader['date'].empty?
170
- connheader['date'] = cv[1]
171
- connvalues += 1
172
- end
128
+ # Continued line of the value of Diagnostic-Code field
129
+ next unless p.start_with?('Diagnostic-Code:')
130
+ next unless cv = e.match(/\A[ \t]+(.+)\z/)
131
+ v['diagnosis'] << ' ' << cv[1]
132
+ havepassed[-1] = 'Diagnostic-Code: ' << e
173
133
  end
174
- end
134
+ end # End of message/delivery-status
175
135
  end
176
136
  return nil unless recipients > 0
177
137
 
178
138
  dscontents.each do |e|
179
139
  # Set default values if each value is empty.
180
- connheader.each_key { |a| e[a] ||= connheader[a] || '' }
140
+ e['lhost'] ||= permessage['rhost']
141
+ permessage.each_key { |a| e[a] ||= permessage[a] || '' }
181
142
  e['command'] = commandset.shift || ''
182
143
  e['agent'] = self.smtpagent
183
144
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
@@ -185,7 +146,7 @@ module Sisimai::Bite::Email
185
146
  ReFailures.each_key do |r|
186
147
  # Verify each regular expression of session errors
187
148
  next unless e['diagnosis'] =~ ReFailures[r]
188
- e['reason'] = r.to_s
149
+ e['reason'] = r
189
150
  break
190
151
  end
191
152
  end