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
data/lib/sisimai/arf.rb CHANGED
@@ -4,6 +4,7 @@ module Sisimai
4
4
  # Imported from p5-Sisimail/lib/Sisimai/ARF.pm
5
5
  class << self
6
6
  require 'sisimai/bite/email'
7
+ require 'sisimai/rfc5322'
7
8
 
8
9
  # http://tools.ietf.org/html/rfc5965
9
10
  # http://en.wikipedia.org/wiki/Feedback_loop_(email)
@@ -48,12 +49,13 @@ module Sisimai
48
49
  elsif heads['content-type'].start_with?('multipart/mixed')
49
50
  # Microsoft (Hotmail, MSN, Live, Outlook) uses its own report format.
50
51
  # Amazon SES Complaints bounces
52
+ hfrom = Sisimai::Address.s3s4(heads['from'])
51
53
  mfrom = %r{(?:
52
54
  staff[@]hotmail[.]com
53
55
  |complaints[@]email-abuse[.]amazonses[.]com
54
56
  )\z
55
57
  }x
56
- if heads['from'] =~ mfrom && heads['subject'].include?('complaint about message from ')
58
+ if hfrom =~ mfrom && heads['subject'].include?('complaint about message from ')
57
59
  # From: staff@hotmail.com
58
60
  # From: complaints@email-abuse.amazonses.com
59
61
  # Subject: complaint about message from 192.0.2.1
@@ -85,16 +87,16 @@ module Sisimai
85
87
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
86
88
  rcptintext = '' # (String) Recipient address in the message body
87
89
  commondata = {
88
- :diagnosis => '', # Error message
89
- :from => '', # Original-Mail-From:
90
- :rhost => '', # Reporting-MTA:
90
+ 'diagnosis' => '', # Error message
91
+ 'from' => '', # Original-Mail-From:
92
+ 'rhost' => '', # Reporting-MTA:
91
93
  }
92
94
  arfheaders = {
93
- :feedbacktype => nil, # FeedBack-Type:
94
- :rhost => nil, # Source-IP:
95
- :agent => nil, # User-Agent:
96
- :date => nil, # Arrival-Date:
97
- :authres => nil, # Authentication-Results:
95
+ 'feedbacktype' => nil, # FeedBack-Type:
96
+ 'rhost' => nil, # Source-IP:
97
+ 'agent' => nil, # User-Agent:
98
+ 'date' => nil, # Arrival-Date:
99
+ 'authres' => nil, # Authentication-Results:
98
100
  }
99
101
  v = nil
100
102
 
@@ -120,7 +122,7 @@ module Sisimai
120
122
  #
121
123
  while e = hasdivided.shift do
122
124
  if readcursor == 0
123
- # Beginning of the bounce message or delivery status part
125
+ # Beginning of the bounce message or message/delivery-status part
124
126
  if e =~ MarkingsOf[:message]
125
127
  readcursor |= Indicators[:deliverystatus]
126
128
  next
@@ -136,7 +138,7 @@ module Sisimai
136
138
  end
137
139
 
138
140
  if readcursor & Indicators[:'message-rfc822'] > 0
139
- # After "message/rfc822"
141
+ # message/rfc822 OR text/rfc822-headers part
140
142
  if cv = e.match(/X-HmXmrOriginalRecipient:[ ]*(.+)\z/)
141
143
  # Microsoft ARF: original recipient.
142
144
  dscontents[-1]['recipient'] = Sisimai::Address.s3s4(cv[1])
@@ -145,17 +147,24 @@ module Sisimai
145
147
  # The "X-HmXmrOriginalRecipient" header appears only once so
146
148
  # we take this opportunity to hard-code ARF headers missing in
147
149
  # Microsoft's implementation.
148
- arfheaders[:feedbacktype] = 'abuse'
149
- arfheaders[:agent] = 'Microsoft Junk Mail Reporting Program'
150
+ arfheaders['feedbacktype'] = 'abuse'
151
+ arfheaders['agent'] = 'Microsoft Junk Mail Reporting Program'
150
152
 
151
153
  elsif cv = e.match(/\AFrom:[ ]*(.+)\z/)
152
154
  # Microsoft ARF: original sender.
153
- commondata[:from] = Sisimai::Address.s3s4(cv[1]) if commondata[:from].empty?
155
+ commondata['from'] = Sisimai::Address.s3s4(cv[1]) if commondata['from'].empty?
154
156
 
155
- elsif cv = e.match(/\A([-0-9A-Za-z]+?)[:][ ]*(.+)\z/)
157
+ elsif e.start_with?(' ', "\t")
158
+ # Continued line from the previous line
159
+ rfc822part << e + "\n" if LongFields.key?(previousfn)
160
+ next unless e.empty?
161
+ rcptintext << e if previousfn == 'to'
162
+
163
+ else
156
164
  # Get required headers only
157
- lhs = cv[1].downcase
158
- rhs = cv[2]
165
+ (lhs, rhs) = e.split(/:[ ]*/, 2)
166
+ next unless lhs
167
+ lhs.downcase!
159
168
 
160
169
  previousfn = ''
161
170
  next unless RFC822Head.key?(lhs)
@@ -163,15 +172,9 @@ module Sisimai
163
172
  previousfn = lhs
164
173
  rfc822part << e + "\n"
165
174
  rcptintext = rhs if lhs == 'to'
166
-
167
- elsif e.start_with?(' ', "\t")
168
- # Continued line from the previous line
169
- rfc822part << e + "\n" if LongFields.key?(previousfn)
170
- next unless e.empty?
171
- rcptintext << e if previousfn == 'to'
172
175
  end
173
176
  else
174
- # Before "message/rfc822"
177
+ # message/delivery-status part
175
178
  next unless readcursor & Indicators[:deliverystatus] > 0
176
179
  next if e.empty?
177
180
 
@@ -201,7 +204,7 @@ module Sisimai
201
204
  elsif cv = e.match(/\AFeedback-Type:[ ]*([^ ]+)\z/)
202
205
  # The header field MUST appear exactly once.
203
206
  # Feedback-Type: abuse
204
- arfheaders[:feedbacktype] = cv[1]
207
+ arfheaders['feedbacktype'] = cv[1]
205
208
 
206
209
  elsif cv = e.match(/\AAuthentication-Results:[ ]*(.+)\z/)
207
210
  # "Authentication-Results" indicates the result of one or more
@@ -209,68 +212,68 @@ module Sisimai
209
212
  #
210
213
  # Authentication-Results: mail.example.com;
211
214
  # spf=fail smtp.mail=somespammer@example.com
212
- arfheaders[:authres] = cv[1]
215
+ arfheaders['authres'] = cv[1]
213
216
 
214
217
  elsif cv = e.match(/\AUser-Agent:[ ]*(.+)\z/)
215
218
  # The header field MUST appear exactly once.
216
219
  # User-Agent: SomeGenerator/1.0
217
- arfheaders[:agent] = cv[1]
220
+ arfheaders['agent'] = cv[1]
218
221
 
219
222
  elsif cv = e.match(/\A(?:Received|Arrival)-Date:[ ]*(.+)\z/)
220
223
  # Arrival-Date header is optional and MUST NOT appear more than
221
224
  # once.
222
225
  # Received-Date: Thu, 29 Apr 2010 00:00:00 JST
223
226
  # Arrival-Date: Thu, 29 Apr 2010 00:00:00 +0000
224
- arfheaders[:date] = cv[1]
227
+ arfheaders['date'] = cv[1]
225
228
 
226
229
  elsif cv = e.match(/\AReporting-MTA:[ ]*dns;[ ]*(.+)\z/)
227
230
  # The header is optional and MUST NOT appear more than once.
228
231
  # Reporting-MTA: dns; mx.example.jp
229
- commondata[:rhost] = cv[1]
232
+ commondata['rhost'] = cv[1]
230
233
 
231
234
  elsif cv = e.match(/\ASource-IP:[ ]*(.+)\z/)
232
235
  # The header is optional and MUST NOT appear more than once.
233
236
  # Source-IP: 192.0.2.45
234
- arfheaders[:rhost] = cv[1]
237
+ arfheaders['rhost'] = cv[1]
235
238
 
236
239
  elsif cv = e.match(/\AOriginal-Mail-From:[ ]*(.+)\z/)
237
240
  # the header is optional and MUST NOT appear more than once.
238
241
  # Original-Mail-From: <somespammer@example.net>
239
- commondata[:from] = Sisimai::Address.s3s4(cv[1]) if commondata[:from].empty?
242
+ commondata['from'] = Sisimai::Address.s3s4(cv[1]) if commondata['from'].empty?
240
243
 
241
244
  elsif e =~ MarkingsOf[:message]
242
245
  # This is an email abuse report for an email message with the
243
246
  # message-id of 0000-000000000000000000000000000000000@mx
244
247
  # received from IP address 192.0.2.1 on
245
248
  # Thu, 29 Apr 2010 00:00:00 +0900 (JST)
246
- commondata[:diagnosis] = e
249
+ commondata['diagnosis'] = e
247
250
  end
248
251
  end
249
252
  end
250
253
 
251
- if arfheaders[:feedbacktype] == 'auth-failure' && arfheaders[:authres]
254
+ if arfheaders['feedbacktype'] == 'auth-failure' && arfheaders['authres']
252
255
  # Append the value of Authentication-Results header
253
- commondata[:diagnosis] << ' ' << arfheaders[:authres]
256
+ commondata['diagnosis'] << ' ' << arfheaders['authres']
254
257
  end
255
258
 
256
259
  unless recipients > 0
257
260
  # Insert pseudo recipient address when there is no valid recipient
258
261
  # address in the message.
259
- dscontents[-1]['recipient'] = Sisimai::Address.undisclosed(:r)
262
+ dscontents[-1]['recipient'] = Sisimai::Address.undisclosed('r')
260
263
  recipients = 1
261
264
  end
262
265
 
263
266
  unless rfc822part =~ /\bFrom: [^ ]+[@][^ ]+\b/
264
267
  # There is no "From:" header in the original message
265
268
  # Append the value of "Original-Mail-From" value as a sender address.
266
- rfc822part << 'From: ' << commondata[:from] + "\n" unless commondata[:from].empty?
269
+ rfc822part << 'From: ' << commondata['from'] + "\n" unless commondata['from'].empty?
267
270
  end
268
271
 
269
272
  if cv = mhead['subject'].match(/complaint about message from (\d{1,3}[.]\d{1,3}[.]\d{1,3}[.]\d{1,3})/)
270
273
  # Microsoft ARF: remote host address.
271
- arfheaders[:rhost] = cv[1]
272
- commondata[:diagnosis] =
273
- 'This is a Microsoft email abuse report for an email message received from IP' << arfheaders[:rhost] + ' on ' << mhead['date']
274
+ arfheaders['rhost'] = cv[1]
275
+ commondata['diagnosis'] =
276
+ 'This is a Microsoft email abuse report for an email message received from IP' << arfheaders['rhost'] + ' on ' << mhead['date']
274
277
  end
275
278
 
276
279
  dscontents.each do |e|
@@ -278,32 +281,28 @@ module Sisimai
278
281
  # AOL = http://forums.cpanel.net/f43/aol-brutal-work-71473.html
279
282
  e['recipient'] = Sisimai::Address.s3s4(rcptintext)
280
283
  end
281
- arfheaders.each_key { |a| e[a.to_s] ||= arfheaders[a] || '' }
284
+ arfheaders.each_key { |a| e[a] ||= arfheaders[a] || '' }
282
285
  e.delete('authres')
283
286
 
284
287
  e['softbounce'] = -1
285
- e['diagnosis'] = commondata[:diagnosis] unless e['diagnosis']
288
+ e['diagnosis'] = commondata['diagnosis'] unless e['diagnosis']
286
289
  e['date'] = mhead['date'] if e['date'].empty?
287
-
288
- if e['rhost'].empty?
289
- # Get the remote IP address from the message body
290
- if commondata[:rhost].size > 0
291
- # The value of "Reporting-MTA" header
292
- e['rhost'] = commondata[:rhost]
293
-
294
- elsif cv = e['diagnosis'].match(/\breceived from IP address ([^ ]+)/)
295
- # This is an email abuse report for an email message received
296
- # from IP address 24.64.1.1 on Thu, 29 Apr 2010 00:00:00 +0000
297
- e['rhost'] = cv[1]
298
- end
290
+ e['reason'] = 'feedback'
291
+ e['agent'] = self.smtpagent if e['agent'].empty?
292
+ %w[command action status alias].each { |a| e[a] = '' }
293
+
294
+ # Get the remote IP address from the message body
295
+ next unless e['rhost'].empty?
296
+ if commondata['rhost'].size > 0
297
+ # The value of "Reporting-MTA" header
298
+ e['rhost'] = commondata['rhost']
299
+
300
+ elsif cv = e['diagnosis'].match(/\breceived from IP address ([^ ]+)/)
301
+ # This is an email abuse report for an email message received
302
+ # from IP address 24.64.1.1 on Thu, 29 Apr 2010 00:00:00 +0000
303
+ e['rhost'] = cv[1]
299
304
  end
300
305
 
301
- e['reason'] = 'feedback'
302
- e['command'] = ''
303
- e['action'] = ''
304
- e['status'] = ''
305
- e['alias'] = ''
306
- e['agent'] = self.smtpagent if e['agent'].empty?
307
306
  end
308
307
  return { 'ds' => dscontents, 'rfc822' => rfc822part }
309
308
  end
data/lib/sisimai/bite.rb CHANGED
@@ -30,7 +30,6 @@ module Sisimai
30
30
 
31
31
  def smtpagent(v = ''); return v.to_s.sub(/\ASisimai::Bite::/, ''); end
32
32
  def description; return ''; end
33
-
34
33
  end
35
34
  end
36
35
  end
@@ -1,4 +1,4 @@
1
- module Sisimai
1
+ module Sisimai
2
2
  module Bite
3
3
  # Sisimai::Bite::Email- Base class for Sisimai::Bite::Email::*
4
4
  module Email
@@ -21,23 +21,23 @@ module Sisimai
21
21
  # @return [Array] MTA list with order
22
22
  def index
23
23
  return %w[
24
- Sendmail Postfix Qmail Exim Courier OpenSMTPD Exchange2007 Exchange2003
25
- Google Yahoo GSuite Aol Outlook Office365 SendGrid AmazonSES MailRu
24
+ Sendmail Postfix Qmail Exim Courier OpenSMTPD Office365 Outlook
25
+ Exchange2007 Exchange2003 Yahoo GSuite Aol SendGrid AmazonSES MailRu
26
26
  Yandex MessagingServer Domino Notes ReceivingSES AmazonWorkMail Verizon
27
27
  GMX Bigfoot Facebook Zoho EinsUndEins MessageLabs EZweb KDDI Biglobe
28
- ApacheJames McAfee MXLogic MailFoundry IMailServer
28
+ Amavis ApacheJames McAfee MXLogic MailFoundry IMailServer
29
29
  MFILTER Activehunter InterScanMSS SurfControl MailMarshalSMTP
30
- X1 X2 X3 X4 X5 V5sendmail FML]
30
+ X1 X2 X3 X4 X5 V5sendmail FML Google]
31
31
  end
32
32
 
33
33
  # @abstract MTA list which have one or more extra headers
34
34
  # @return [Array] MTA list (have extra headers)
35
35
  def heads
36
36
  return %w[
37
- Exim Exchange2007 Exchange2003 Google GSuite Office365 Outlook SendGrid
37
+ Exim Office365 Outlook Exchange2007 Exchange2003 GSuite SendGrid
38
38
  AmazonSES ReceivingSES AmazonWorkMail Aol GMX MailRu MessageLabs Yahoo
39
39
  Yandex Zoho EinsUndEins MXLogic McAfee MFILTER EZweb Activehunter IMailServer
40
- SurfControl FML
40
+ SurfControl FML Google
41
41
  ]
42
42
  end
43
43
 
@@ -15,7 +15,7 @@ module Sisimai::Bite::Email
15
15
 
16
16
  def description; return 'TransWARE Active!hunter'; end
17
17
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
18
- def headerlist; return ['X-AHMAILID']; end
18
+ def headerlist; return %w[x-ahmailid]; end
19
19
 
20
20
  # Parse bounce messages from TransWARE Active!hunter
21
21
  # @param [Hash] mhead Message headers of a bounce email
@@ -59,7 +59,7 @@ module Sisimai::Bite::Email
59
59
  end
60
60
 
61
61
  if readcursor & Indicators[:'message-rfc822'] > 0
62
- # After "message/rfc822"
62
+ # Inside of the original message part
63
63
  if e.empty?
64
64
  blanklines += 1
65
65
  break if blanklines > 1
@@ -67,7 +67,7 @@ module Sisimai::Bite::Email
67
67
  end
68
68
  rfc822list << e
69
69
  else
70
- # Before "message/rfc822"
70
+ # Error message part
71
71
  next if (readcursor & Indicators[:deliverystatus]) == 0
72
72
  next if e.empty?
73
73
 
@@ -100,6 +100,7 @@ module Sisimai::Bite::Email
100
100
  end
101
101
  return nil unless recipients > 0
102
102
 
103
+ require 'sisimai/string'
103
104
  dscontents.each do |e|
104
105
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
105
106
  e['agent'] = self.smtpagent
@@ -0,0 +1,133 @@
1
+ module Sisimai::Bite::Email
2
+ # Sisimai::Bite::Email::Amavis parses a bounce email which created by
3
+ # amavsid-new. Methods in the module are called from only Sisimai::Message.
4
+ module Amavis
5
+ class << self
6
+ # Imported from p5-Sisimail/lib/Sisimai/Bite/Email/Amavis.pm
7
+ require 'sisimai/bite/email'
8
+
9
+ Indicators = Sisimai::Bite::Email.INDICATORS
10
+ StartingOf = {
11
+ message: ['The message '],
12
+ rfc822: ['Content-Type: text/rfc822-headers'],
13
+ }.freeze
14
+
15
+ def description; return 'amavisd-new: https://www.amavis.org/'; end
16
+ def smtpagent; return Sisimai::Bite.smtpagent(self); end
17
+
18
+ # Parse bounce messages from amavisd-new
19
+ # @param [Hash] mhead Message headers of a bounce email
20
+ # @options mhead [String] from From header
21
+ # @options mhead [String] date Date header
22
+ # @options mhead [String] subject Subject header
23
+ # @options mhead [Array] received Received headers
24
+ # @options mhead [String] others Other required headers
25
+ # @param [String] mbody Message body of a bounce email
26
+ # @return [Hash, Nil] Bounce data list and message/rfc822
27
+ # part or nil if it failed to parse or
28
+ # the arguments are missing
29
+ def scan(mhead, mbody)
30
+ # From: "Content-filter at neko1.example.jp" <postmaster@neko1.example.jp>
31
+ # Subject: Undeliverable mail, MTA-BLOCKED
32
+ return nil unless mhead['from'].to_s.start_with?('"Content-filter at ')
33
+
34
+ require 'sisimai/rfc1894'
35
+ fieldtable = Sisimai::RFC1894.FIELDTABLE
36
+ permessage = {} # (Hash) Store values of each Per-Message field
37
+
38
+ dscontents = [Sisimai::Bite.DELIVERYSTATUS]
39
+ hasdivided = mbody.split("\n")
40
+ havepassed = ['']
41
+ rfc822list = [] # (Array) Each line in message/rfc822 part string
42
+ blanklines = 0 # (Integer) The number of blank lines
43
+ readcursor = 0 # (Integer) Points the current cursor position
44
+ recipients = 0 # (Integer) The number of 'Final-Recipient' header
45
+ v = nil
46
+
47
+ while e = hasdivided.shift do
48
+ # Save the current line for the next loop
49
+ havepassed << e
50
+ p = havepassed[-2]
51
+
52
+ if readcursor == 0
53
+ # Beginning of the bounce message or message/delivery-status part
54
+ if e.start_with?(StartingOf[:message][0])
55
+ readcursor |= Indicators[:deliverystatus]
56
+ next
57
+ end
58
+ end
59
+
60
+ if (readcursor & Indicators[:'message-rfc822']) == 0
61
+ # Beginning of the original message part(message/rfc822)
62
+ if e == StartingOf[:rfc822][0]
63
+ readcursor |= Indicators[:'message-rfc822']
64
+ next
65
+ end
66
+ end
67
+
68
+ if readcursor & Indicators[:'message-rfc822'] > 0
69
+ # message/rfc822 OR text/rfc822-headers part
70
+ if e.empty?
71
+ blanklines += 1
72
+ break if blanklines > 1
73
+ next
74
+ end
75
+ rfc822list << e
76
+ else
77
+ # message/delivery-status part
78
+ next if (readcursor & Indicators[:deliverystatus]) == 0
79
+ next if e.empty?
80
+ next unless f = Sisimai::RFC1894.match(e)
81
+
82
+ # "e" matched with any field defined in RFC3464
83
+ next unless o = Sisimai::RFC1894.field(e)
84
+ v = dscontents[-1]
85
+
86
+ if o[-1] == 'addr'
87
+ # Final-Recipient: rfc822; kijitora@example.jp
88
+ # X-Actual-Recipient: rfc822; kijitora@example.co.jp
89
+ if o[0] == 'final-recipient'
90
+ # Final-Recipient: rfc822; kijitora@example.jp
91
+ if v['recipient']
92
+ # There are multiple recipient addresses in the message body.
93
+ dscontents << Sisimai::Bite.DELIVERYSTATUS
94
+ v = dscontents[-1]
95
+ end
96
+ v['recipient'] = o[2]
97
+ recipients += 1
98
+ else
99
+ # X-Actual-Recipient: rfc822; kijitora@example.co.jp
100
+ v['alias'] = o[2]
101
+ end
102
+ elsif o[-1] == 'code'
103
+ # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
104
+ v['spec'] = o[1]
105
+ v['diagnosis'] = o[2]
106
+ else
107
+ # Other DSN fields defined in RFC3464
108
+ next unless fieldtable.key?(o[0])
109
+ v[fieldtable[o[0]]] = o[2]
110
+
111
+ next unless f == 1
112
+ permessage[fieldtable[o[0]]] = o[2]
113
+ end
114
+ end # End of message/delivery-status
115
+ end
116
+ return nil unless recipients > 0
117
+
118
+ dscontents.each do |e|
119
+ # Set default values if each value is empty.
120
+ permessage.each_key { |a| e[a] ||= permessage[a] || '' }
121
+
122
+ e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].to_s.tr("\n", ' '))
123
+ e['agent'] = self.smtpagent
124
+ end
125
+
126
+ rfc822part = Sisimai::RFC5322.weedout(rfc822list)
127
+ return { 'ds' => dscontents, 'rfc822' => rfc822part }
128
+ end
129
+
130
+ end
131
+ end
132
+ end
133
+