sisimai 5.7.1-java → 5.8.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/codecovio.yml +1 -1
  3. data/.github/workflows/rake-test.yml +2 -2
  4. data/ChangeLog.md +28 -0
  5. data/Developers.mk +4 -0
  6. data/Makefile +1 -0
  7. data/README-JA.md +32 -16
  8. data/README.md +31 -16
  9. data/lib/sisimai/arf.rb +1 -1
  10. data/lib/sisimai/eb.rb +2 -0
  11. data/lib/sisimai/lhost/activehunter.rb +2 -2
  12. data/lib/sisimai/lhost/amazonses.rb +4 -0
  13. data/lib/sisimai/lhost/apachejames.rb +2 -2
  14. data/lib/sisimai/lhost/biglobe.rb +2 -2
  15. data/lib/sisimai/lhost/courier.rb +2 -2
  16. data/lib/sisimai/lhost/deutschetelekom.rb +2 -2
  17. data/lib/sisimai/lhost/domino.rb +3 -4
  18. data/lib/sisimai/lhost/dragonfly.rb +2 -2
  19. data/lib/sisimai/lhost/einsundeins.rb +2 -2
  20. data/lib/sisimai/lhost/exchange2003.rb +2 -2
  21. data/lib/sisimai/lhost/exchange2007.rb +2 -2
  22. data/lib/sisimai/lhost/exim.rb +2 -2
  23. data/lib/sisimai/lhost/ezweb.rb +2 -2
  24. data/lib/sisimai/lhost/fml.rb +2 -2
  25. data/lib/sisimai/lhost/gmail.rb +2 -2
  26. data/lib/sisimai/lhost/gmx.rb +2 -2
  27. data/lib/sisimai/lhost/googlegroups.rb +1 -1
  28. data/lib/sisimai/lhost/googleworkspace.rb +2 -2
  29. data/lib/sisimai/lhost/imailserver.rb +2 -2
  30. data/lib/sisimai/lhost/kddi.rb +2 -2
  31. data/lib/sisimai/lhost/mailfoundry.rb +2 -2
  32. data/lib/sisimai/lhost/mailmarshal.rb +2 -2
  33. data/lib/sisimai/lhost/messagingserver.rb +2 -2
  34. data/lib/sisimai/lhost/mfilter.rb +2 -2
  35. data/lib/sisimai/lhost/mimecast.rb +2 -2
  36. data/lib/sisimai/lhost/notes.rb +2 -2
  37. data/lib/sisimai/lhost/opensmtpd.rb +2 -2
  38. data/lib/sisimai/lhost/postfix.rb +3 -3
  39. data/lib/sisimai/lhost/qmail.rb +2 -2
  40. data/lib/sisimai/lhost/sendmail.rb +4 -4
  41. data/lib/sisimai/lhost/trendmicro.rb +2 -2
  42. data/lib/sisimai/lhost/v5sendmail.rb +2 -4
  43. data/lib/sisimai/lhost/verizon.rb +4 -4
  44. data/lib/sisimai/lhost/x1.rb +2 -2
  45. data/lib/sisimai/lhost/x2.rb +2 -2
  46. data/lib/sisimai/lhost/x3.rb +2 -2
  47. data/lib/sisimai/lhost/x6.rb +2 -2
  48. data/lib/sisimai/lhost/zoho.rb +2 -2
  49. data/lib/sisimai/mail/maildir.rb +4 -2
  50. data/lib/sisimai/mail/stdin.rb +3 -3
  51. data/lib/sisimai/message.rb +9 -8
  52. data/lib/sisimai/reason/authfailure.rb +1 -0
  53. data/lib/sisimai/reason/blocked.rb +1 -0
  54. data/lib/sisimai/reason/ratelimited.rb +3 -2
  55. data/lib/sisimai/reason/requireptr.rb +1 -0
  56. data/lib/sisimai/reason/userunknown.rb +1 -0
  57. data/lib/sisimai/rfc3464.rb +5 -6
  58. data/lib/sisimai/rfc5322.rb +0 -1
  59. data/lib/sisimai/rhost/google.rb +11 -9
  60. data/lib/sisimai/smtp/status.rb +1 -1
  61. data/lib/sisimai/string.rb +4 -3
  62. data/lib/sisimai/version.rb +1 -1
  63. data/lib/sisimai.rb +28 -4
  64. data/set-of-emails/mailbox/mbox-2 +141 -0
  65. metadata +3 -2
@@ -26,9 +26,9 @@ module Sisimai::Lhost
26
26
  proceedsto = true if StartingOf[:command].any? { |a| mbody.include?(a) }
27
27
  return nil if proceedsto == false
28
28
 
29
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
30
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
29
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries); return nil if emailparts.nil? || emailparts[0].empty?
31
30
  bodyslices = emailparts[0].split("\n")
31
+ dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
32
32
  readcursor = 0 # (Integer) Points the current cursor position
33
33
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
34
34
  markingset = {'diagnosis' => false, 'command' => false}
@@ -28,9 +28,9 @@ module Sisimai::Lhost
28
28
  fieldtable = Sisimai::RFC1894.FIELDTABLE
29
29
  permessage = {} # (Hash) Store values of each Per-Message field
30
30
 
31
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
32
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
31
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries); return nil if emailparts.nil? || emailparts[0].empty?
33
32
  bodyslices = emailparts[0].split("\n")
33
+ dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
34
34
  readcursor = 0 # (Integer) Points the current cursor position
35
35
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
36
36
 
@@ -24,9 +24,9 @@ module Sisimai::Lhost
24
24
  def inquire(mhead, mbody)
25
25
  return nil if mhead['subject'].start_with?('Undeliverable message') == false
26
26
 
27
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
28
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
27
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries); return nil if emailparts.nil? || emailparts[0].empty?
29
28
  bodyslices = emailparts[0].split("\n")
29
+ dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
30
30
  readcursor = 0 # (Integer) Points the current cursor position
31
31
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
32
32
  characters = '' # (String) Character set name of the bounce mail
@@ -46,9 +46,9 @@ module Sisimai::Lhost
46
46
  return nil if mhead['from'].start_with?('Mailer Daemon <') == false
47
47
  return nil if mhead['received'].none? { |a| a.include?(' (OpenSMTPD) with ') }
48
48
 
49
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
50
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
49
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries); return nil if emailparts.nil? || emailparts[0].empty?
51
50
  bodyslices = emailparts[0].split("\n")
51
+ dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
52
52
  readcursor = 0 # (Integer) Points the current cursor position
53
53
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
54
54
 
@@ -42,11 +42,11 @@ module Sisimai::Lhost
42
42
  end
43
43
  return nil if match == 0 || mhead['x-aol-ip']
44
44
 
45
- permessage = {} # (Hash) Store values of each Per-Message field
46
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
47
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
45
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries); return nil if emailparts.nil? || emailparts[0].empty?
48
46
  bodyslices = emailparts[0].split("\n")
47
+ dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
49
48
  readslices = ['']
49
+ permessage = {} # (Hash) Store values of each Per-Message field
50
50
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
51
51
  nomessages = false # (Boolean) Delivery report unavailable
52
52
  commandset = [] # (Array) ``in reply to * command'' list
@@ -93,9 +93,9 @@ module Sisimai::Lhost
93
93
  return nil if proceedsto == false
94
94
 
95
95
  require "sisimai/smtp/command"
96
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
97
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
96
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries); return nil if emailparts.nil? || emailparts[0].empty?
98
97
  bodyslices = emailparts[0].split("\n")
98
+ dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
99
99
  readcursor = 0 # (Integer) Points the current cursor position
100
100
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
101
101
 
@@ -37,12 +37,12 @@ module Sisimai::Lhost
37
37
  match ||= true if mhead['subject'].start_with?('Warning: ')
38
38
  return nil if match == false
39
39
 
40
- fieldtable = Sisimai::RFC1894.FIELDTABLE
41
- permessage = {} # (Hash) Store values of each Per-Message field
42
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
43
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
40
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries); return nil if emailparts.nil? || emailparts[0].empty?
44
41
  bodyslices = emailparts[0].split("\n")
42
+ dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
43
+ fieldtable = Sisimai::RFC1894.FIELDTABLE
45
44
  readslices = ['']
45
+ permessage = {} # (Hash) Store values of each Per-Message field
46
46
  readcursor = 0 # (Integer) Points the current cursor position
47
47
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
48
48
  thecommand = '' # (String) SMTP Command name begin with the string '>>>'
@@ -27,9 +27,9 @@ module Sisimai::Lhost
27
27
  return nil if match == 0
28
28
 
29
29
  require 'sisimai/smtp/command'
30
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
31
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
30
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries); return nil if emailparts.nil? || emailparts[0].empty?
32
31
  bodyslices = emailparts[0].split("\n")
32
+ dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
33
33
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
34
34
 
35
35
  while e = bodyslices.shift do
@@ -38,14 +38,12 @@ module Sisimai::Lhost
38
38
  # :from => %r/\AMail Delivery Subsystem/,
39
39
  return nil if mhead['subject'].start_with?('Returned mail: ') == false
40
40
 
41
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
42
- return nil if emailparts[1].size == 0
43
-
44
41
  require 'sisimai/eb'
45
42
  require 'sisimai/rfc1123'
46
43
  require 'sisimai/smtp/command'
47
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
44
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries); return nil if emailparts.nil? || emailparts[1].empty?
48
45
  bodyslices = emailparts[0].split("\n")
46
+ dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
49
47
  readcursor = 0 # (Integer) Points the current cursor position
50
48
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
51
49
  anotherone = {} # (Hash) Another error information
@@ -41,7 +41,7 @@ module Sisimai::Lhost
41
41
  Sisimai::Eb::ReUSER => ['550 - Requested action not taken: no such user here'],
42
42
  }
43
43
  boundaries = [Sisimai::RFC2045.boundary(mhead['content-type'], 1)]
44
- emailparts = Sisimai::RFC5322.part(mbody, boundaries)
44
+ emailparts = Sisimai::RFC5322.part(mbody, boundaries); return nil if emailparts.nil? || emailparts[0].empty?
45
45
  bodyslices = emailparts[0].split("\n")
46
46
 
47
47
  while e = bodyslices.shift do
@@ -85,11 +85,11 @@ module Sisimai::Lhost
85
85
  end
86
86
  else
87
87
  # vzwpix.com
88
- startingof = {message: ['Message could not be delivered to mobile']}
89
- messagesof = {Sisimai::Eb::ReUSER => ['No valid recipients for this MM']}
90
88
  boundaries = [Sisimai::RFC2045.boundary(mhead['content-type'], 1)]
91
- emailparts = Sisimai::RFC5322.part(mbody, boundaries)
89
+ emailparts = Sisimai::RFC5322.part(mbody, boundaries); return nil if emailparts.nil? || emailparts[0].empty?
92
90
  bodyslices = emailparts[0].split("\n")
91
+ startingof = {message: ['Message could not be delivered to mobile']}
92
+ messagesof = {Sisimai::Eb::ReUSER => ['No valid recipients for this MM']}
93
93
 
94
94
  while e = bodyslices.shift do
95
95
  # Read error messages and delivery status lines from the head of the email to the previous
@@ -21,9 +21,9 @@ module Sisimai::Lhost
21
21
  proceedsto = true if Sisimai::String.aligned(mhead['from'], ['"Mail Deliver', 'System" '])
22
22
  return nil if proceedsto == false
23
23
 
24
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
25
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
24
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries); return nil if emailparts.nil? || emailparts[0].empty?
26
25
  bodyslices = emailparts[0].split("\n")
26
+ dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
27
27
  readcursor = 0 # (Integer) Points the current cursor position
28
28
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
29
29
  datestring = '' # (String) Date string
@@ -26,9 +26,9 @@ module Sisimai::Lhost
26
26
  match ||= true if mhead['subject'].start_with?('failed delivery')
27
27
  return nil if match == false
28
28
 
29
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
30
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
29
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries); return nil if emailparts.nil? || emailparts[0].empty?
31
30
  bodyslices = emailparts[0].split("\n")
31
+ dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
32
32
  readcursor = 0 # (Integer) Points the current cursor position
33
33
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
34
34
 
@@ -19,9 +19,9 @@ module Sisimai::Lhost
19
19
  return nil if mhead['from'].start_with?('Mail Delivery System') == false
20
20
 
21
21
  require 'sisimai/smtp/command'
22
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
23
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
22
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries); return nil if emailparts.nil? || emailparts[0].empty?
24
23
  bodyslices = emailparts[0].split("\n")
24
+ dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
25
25
  readcursor = 0 # (Integer) Points the current cursor position
26
26
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
27
27
  v = nil
@@ -18,9 +18,9 @@ module Sisimai::Lhost
18
18
  def inquire(mhead, mbody)
19
19
  return nil if mhead['subject'].start_with?('There was an error sending your mail') == false
20
20
 
21
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
22
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
21
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries); return nil if emailparts.nil? || emailparts[0].empty?
23
22
  bodyslices = emailparts[0].split("\n")
23
+ dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
24
24
  readcursor = 0 # (Integer) Points the current cursor position
25
25
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
26
26
 
@@ -20,9 +20,9 @@ module Sisimai::Lhost
20
20
  # X-Mailer: Zoho Mail
21
21
  return nil if mhead['x-zohomail'].nil?
22
22
 
23
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
24
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
23
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries); return nil if emailparts.nil? || emailparts[0].empty?
25
24
  bodyslices = emailparts[0].split("\n")
25
+ dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
26
26
  readcursor = 0 # (Integer) Points the current cursor position
27
27
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
28
28
  qprintable = false
@@ -34,6 +34,7 @@ module Sisimai
34
34
  seekhandle = self.handle
35
35
  readbuffer = ''
36
36
 
37
+ require 'sisimai/eb'
37
38
  begin
38
39
  while r = seekhandle.read do
39
40
  # Read each file in the directory
@@ -44,9 +45,10 @@ module Sisimai
44
45
  end
45
46
 
46
47
  emailindir = (self.dir + '/' + r).squeeze('/')
48
+ emailbytes = File.size(emailindir)
47
49
  if File.ftype(emailindir) != 'file' ||
48
- File.size(emailindir) == 0 ||
49
- File.readable?(emailindir) == false
50
+ File.readable?(emailindir) == false ||
51
+ emailbytes < 1 || emailbytes > Sisimai::Eb::XeBYTE
50
52
  # The file is not a file, is empty, is not readable
51
53
  self.offset += 1
52
54
  next
@@ -6,8 +6,8 @@ module Sisimai
6
6
  # :size [Integer] Data size which has been read
7
7
  # :offset [Integer] The number of emails which have neen read
8
8
  # :handle [IO::File] File handle
9
- attr_reader :path, :name, :size
10
- attr_accessor :offset, :handle
9
+ attr_reader :path, :name
10
+ attr_accessor :offset, :handle, :size
11
11
 
12
12
  # Constructor of Sisimai::Mail::STDIN
13
13
  # @param [IO::STDIN] stdin Standard-In
@@ -16,7 +16,7 @@ module Sisimai
16
16
  raise 'is not an IO object' if stdin.is_a?(IO) == false
17
17
 
18
18
  @path = '<STDIN>'
19
- @size = nil
19
+ @size = 0
20
20
  @offset = 0
21
21
  @handle = stdin
22
22
  end
@@ -86,7 +86,8 @@ module Sisimai
86
86
  # There is a bounce message inside of mutipart/*, try to sift the first message/rfc822
87
87
  # part as a entire message body again.
88
88
  parseagain += 1
89
- email = Sisimai::RFC5322.part(aftersplit[2], Boundaries, true).pop.sub(/\A\s+/, '')
89
+ email = Sisimai::RFC5322.part(aftersplit[2], Boundaries, true); break if email.nil?
90
+ email = email.pop.sub(/\A\s+/, '')
90
91
  break if email.size < 128
91
92
  end
92
93
  return nil if beforefact.nil? || beforefact.empty?
@@ -202,7 +203,7 @@ module Sisimai
202
203
  def tidy(argv0 = '')
203
204
  return '' if argv0.empty?
204
205
 
205
- email = ''
206
+ email = ::String.new(capacity: argv0.bytesize, encoding: Encoding::UTF_8)
206
207
  lines = argv0.split("\n")
207
208
  index = -1
208
209
  lines.each do |e|
@@ -215,7 +216,7 @@ module Sisimai
215
216
  index += 1
216
217
  if fn == ''
217
218
  # There is neither ":" character nor the field listed in $FieldTable
218
- email += "#{e}\n"
219
+ email << e << "\n"
219
220
  next
220
221
  end
221
222
 
@@ -294,12 +295,12 @@ module Sisimai
294
295
 
295
296
  # 4. Remove redundant space characters
296
297
  bf = bf.squeeze(' ').strip
297
- email += sprintf("%s: %s\n", fn, bf)
298
+ email << sprintf("%s: %s\n", fn, bf)
298
299
  end
299
300
 
300
301
  # 5. Convert the lower-cased SMTP command to the upper-cased.
301
- email = email.gsub("after end of data:", "after end of DATA:")
302
- email += "\n" if email.end_with?("\n\n") == false
302
+ email.gsub!("after end of data:", "after end of DATA:")
303
+ email << "\n" if email.end_with?("\n\n") == false
303
304
  return email
304
305
  end
305
306
 
@@ -314,7 +315,7 @@ module Sisimai
314
315
  # @param options argvs [Array] tryonfirst MTA module list to load on first
315
316
  # @return [Hash] Decoded and structured bounce mails
316
317
  def sift(argvs)
317
- return nil if argvs['mail'].nil? || argvs['body'].nil?
318
+ return nil if argvs['mail'].nil? || argvs['body'].nil? || argvs['body'].empty?
318
319
 
319
320
  mailheader = argvs['mail']['header']
320
321
  bodystring = argvs['body']
@@ -356,6 +357,7 @@ module Sisimai
356
357
  bodystring = p if p.empty? == false
357
358
  end
358
359
  bodystring = bodystring.scrub('?').delete("\r").gsub("\t", " ")
360
+ return nil if bodystring.empty?
359
361
 
360
362
  haveloaded = {}
361
363
  havesifted = nil
@@ -428,4 +430,3 @@ module Sisimai
428
430
  end
429
431
  end
430
432
  end
431
-
@@ -20,6 +20,7 @@ module Sisimai
20
20
  "dmarc policy",
21
21
  "doesn't meet the required authentication level",
22
22
  "please inspect your spf settings",
23
+ "rejected due to dmarc", # comcast.net
23
24
  "sender policy framework",
24
25
  "spf check: fail",
25
26
  ].freeze
@@ -23,6 +23,7 @@ module Sisimai
23
23
  "error: no valid recipients from ",
24
24
  "esmtp not accepting connections", # icloud.com
25
25
  "extreme bad ip profile",
26
+ "found on one or more dnsbls", # comcast.net
26
27
  "helo command rejected:",
27
28
  "host network not allowed",
28
29
  "invalid ip for sending mail of domain",
@@ -18,8 +18,6 @@ module Sisimai
18
18
  "temporarily deferred due to unexpected volume or user complaints",
19
19
  "throttling failure: ",
20
20
  "too many errors from your ip", # Free.fr
21
- "too many recipients", # ntt docomo
22
- "too many smtp sessions for this host", # Sendmail(daemon.c)
23
21
  "trop de connexions, ",
24
22
  "we have already made numerous attempts to deliver this message",
25
23
  ].freeze
@@ -27,6 +25,9 @@ module Sisimai
27
25
  ["exceeded ", "allowable number of posts without solving a captcha"],
28
26
  ["connection ", "limit"],
29
27
  ["temporarily", "rate limited"],
28
+ ["throttled ", "postmaster.comcast.net"],
29
+ ["too many ", "session"], # Sendmail(daemon.c), comcast.net
30
+ ["too many ", "recipients"], # nttdocomo, comcast.net
30
31
  ["too many con", "s"],
31
32
  ].freeze
32
33
 
@@ -13,6 +13,7 @@ module Sisimai
13
13
  "corresponding forward dns entry does not point to the sending ip", # Google
14
14
  "ip name lookup failed",
15
15
  "no matches to nameserver query",
16
+ "ptr lookup failure",
16
17
  "sender ip reverse lookup rejected",
17
18
  "unresolvable relay host name",
18
19
  ].freeze
@@ -67,6 +67,7 @@ module Sisimai
67
67
  "recipient is not accepted",
68
68
  "recipient is not in my validrcptto list",
69
69
  "recipient is not local",
70
+ "recipient mailbox unallocated", # comcast.net
70
71
  "recipient not ok",
71
72
  "recipient refuses to accept your mail",
72
73
  "recipient unknown",
@@ -35,11 +35,10 @@ module Sisimai
35
35
  p0 = mbody.index("\n\nReturn-Path:")
36
36
  mbody = sprintf("%s%s%s", mbody[0, p0], Boundaries[0], mbody[p0 + 1, mbody.size]) if p0
37
37
  end
38
-
39
- permessage = {}
38
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries); return nil if emailparts.nil?
40
39
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
41
40
  alternates = Sisimai::Lhost.DELIVERYSTATUS
42
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
41
+ permessage = {}
43
42
  readslices = [""]
44
43
  readcursor = 0 # (Integer) Points the current cursor position
45
44
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
@@ -62,12 +61,13 @@ module Sisimai
62
61
  end
63
62
  break if p0.nil?
64
63
 
65
- cx = mbody[p1, mbody.size]
66
- p2 = cx.index("\n\n")
64
+ cx = mbody[p1, mbody.size]; return nil if cx.nil?
65
+ p2 = cx.index("\n\n"); return nil if p2.nil?
67
66
  cv = cx[p2 + 2, mbody.size]
68
67
  emailparts = Sisimai::RFC5322.part(cv, [ct], 0)
69
68
  break
70
69
  end
70
+ return nil if emailparts.nil?
71
71
 
72
72
  if emailparts[0].index(StartingOf[:message][0]) == nil
73
73
  # There is no "Content-Type: message/delivery-status" line in the message body
@@ -272,4 +272,3 @@ module Sisimai
272
272
  end
273
273
  end
274
274
  end
275
-
@@ -202,7 +202,6 @@ module Sisimai
202
202
  end
203
203
  latterpart << "\n" if latterpart.end_with?("\n") == false
204
204
  end
205
-
206
205
  return [formerpart, latterpart]
207
206
  end
208
207
 
@@ -230,8 +230,9 @@ module Sisimai
230
230
  ['550', '5.7.1', 'email quota exceeded'],
231
231
  ],
232
232
  Sisimai::Eb::ReINET => [
233
- # - 554 5.4.6 Message exceeded 50 hops, this may indicate a mail loop.
234
- # For more information, go to Gmail Help. https://support.google.com/mail/?p=MailLoop
233
+ # - 554 5.4.6 Message exceeded 50 hops, this may show a mail loop. For details,
234
+ # go to SMTP relay service error messages.
235
+ # - https://support.google.com/mail/?p=MailLoop
235
236
  ['554', '5.4.6', 'message exceeded 50 hops'],
236
237
  ['554', '5.6.0', 'message exceeded 50 hops'],
237
238
  ],
@@ -389,9 +390,10 @@ module Sisimai
389
390
  ['550', '5.7.25', 'does not match the ip address of the hostname'],
390
391
  ],
391
392
  Sisimai::Eb::ReSAFE => [
392
- # - 454 4.7.0 Too many login attempts, please try again later. For more information, go
393
- # to Add Gmail to another email client. https://support.google.com/mail/answer/7126229
394
- ['454', '4.7.0', 'too many login attempts'],
393
+ # - 454 4.7.0 Too many sign-in attempts, try again later. For details,
394
+ # go to SMTP relay service error messages.
395
+ # - https://support.google.com/mail/answer/7126229
396
+ ['454', '4.7.0', 'too many sign-in attempts'],
395
397
 
396
398
  # - 503 5.7.0 No identity changes permitted. For more information, go to About SMTP
397
399
  # error messages.
@@ -496,10 +498,10 @@ module Sisimai
496
498
  # https://support.google.com/a/answer/7282433
497
499
  ['452', '4.5.3', 'domain policy size per transaction exceeded'],
498
500
 
499
- # - 454 4.7.0 Cannot authenticate due to a temporary system problem. Try again later.
500
- # For more information, go to About SMTP error messages.
501
- # https://support.google.com/a/answer/3221692
502
- ['454', '4.7.0', 'cannot authenticate due to temporary system problem'],
501
+ # - 454 4.7.0 Cannot sign in due to a temporary system problem. Try again later.
502
+ # For details, go to SMTP relay service error messages.
503
+ # - https://support.google.com/a/answer/3221692
504
+ ['454', '4.7.0', 'cannot sign in due to a temporary system problem'],
503
505
  ],
504
506
  Sisimai::Eb::ReUSER => [
505
507
  # - 550 5.1.1 The email account that you tried to reach does not exist. Please try dou-
@@ -572,7 +572,7 @@ module Sisimai
572
572
  '5.6.3' => Sisimai::Eb::ReBODY, # Conversion required but not supported
573
573
  '5.6.5' => Sisimai::Eb::ReBODY, # Conversion Failed
574
574
  '5.6.6' => Sisimai::Eb::ReBODY, # Message content not available
575
- '5.6.7' => Sisimai::Eb::ReFROM, # Non-ASCII addresses not permitted for that sender/recipient
575
+ '5.6.7' => Sisimai::Eb::RePROC, # Non-ASCII addresses not permitted for that sender/recipient
576
576
  '5.6.8' => Sisimai::Eb::ReBODY, # UTF-8 string reply is required, but not permitted by the SMTP client
577
577
  '5.6.9' => Sisimai::Eb::ReBODY, # UTF-8 header message cannot be transferred to one or more recipients
578
578
  '5.7.0' => Sisimai::Eb::ReSAFE, # Other or undefined security status
@@ -53,9 +53,10 @@ module Sisimai
53
53
  # 3. <a href = 'http://...'>...</a> to " http://... "
54
54
  # 4. <a href = 'mailto:...'>...</a> to " Value <mailto:...> "
55
55
  plain.scrub!('?')
56
- plain = plain.gsub(%r|<head>.+</head>|im, '')
57
- plain = plain.gsub(%r|<style.+?>.+</style>|im, '')
58
- plain = plain.gsub(%r|<a\s+href\s*=\s*['"](https?://.+?)['"].*?>(.*?)</a>|i, '[\2](\1)')
56
+ cv = plain.downcase
57
+ plain = plain.gsub(%r|<head>.+?</head>|im, "") if cv.include?("</head>")
58
+ plain = plain.gsub(%r|<style.+?>.+?</style>|im, "") if cv.include?("</style>")
59
+ plain = plain.gsub(%r|<a\s+href\s*=\s*(['"])(https?://[^'"]+?)\1[^>]*?>(.*?)</a>|i, ' [\3](\2) ')
59
60
  plain = plain.gsub(%r|<a\s+href\s*=\s*["']mailto:([^\s]+?)["']>(.*?)</a>|i, '[\2](mailto:\1)')
60
61
  plain = plain.gsub(/<[^<@>]+?>\s*/, ' ') # Delete HTML tags except <neko@example.jp>
61
62
  plain = plain.gsub(/&lt;/, '<').gsub(/&gt;/, '>') # Convert to angle brackets
@@ -1,4 +1,4 @@
1
1
  # Define the version number of Sisimai
2
2
  module Sisimai
3
- VERSION = '5.7.1'.freeze
3
+ VERSION = '5.8.0'.freeze
4
4
  end
data/lib/sisimai.rb CHANGED
@@ -19,16 +19,40 @@ module Sisimai
19
19
  # @return [nil] nil if the argument was wrong or an empty array
20
20
  def rise(argv0, **argv1)
21
21
  return nil unless argv0
22
+ require 'sisimai/eb'
22
23
  require 'sisimai/mail'
23
24
  require 'sisimai/fact'
24
-
25
25
  return nil unless mail = Sisimai::Mail.new(argv0)
26
- kind = mail.kind
26
+
27
+ maxb = Sisimai::Eb::XeBYTE * 32 # 64MB * 32 = 2GB
28
+ if (mail.kind == "mailbox" || mail.kind == "memory") && (mail.data.size > maxb || mail.data.size < 1)
29
+ # Check and limit the max size of entire email data: UNIX mbox and memory: 2GB
30
+ warn " ***warning: Input email is empty or too large: #{mail.data.size} bytes"
31
+ return nil
32
+ end
33
+
27
34
  c___ = argv1[:c___].is_a?(Array) ? argv1[:c___] : [nil, nil]
28
35
  sisi = []
29
-
36
+ sumb = 0
30
37
  while r = mail.data.read do
31
38
  # Read and decode each email file
39
+ if mail.kind == 'maildir'
40
+ # - Check and limit the max size of each email file (64MB)
41
+ # - Skip to the next email when the size of email is larger than 64MB.
42
+ next if mail.data.size > Sisimai::Eb::XeBYTE
43
+ else
44
+ # UNIX mbox, memory, and stdin.
45
+ next if r.bytesize > Sisimai::Eb::XeBYTE
46
+
47
+ if mail.kind == "stdin"
48
+ # Check and limit the max size of entire email data read from STDIN: 2GB
49
+ sumb += r.bytesize; if sumb > maxb
50
+ warn " ***warning: Input email is too large: #{sumb} bytes"
51
+ return nil
52
+ end
53
+ end
54
+ end
55
+
32
56
  path = mail.data.path
33
57
  args = {data: r, hook: c___[0], origin: path, delivered: argv1[:delivered], vacation: argv1[:vacation]}
34
58
  fact = Sisimai::Fact.rise(**args) || []
@@ -36,7 +60,7 @@ module Sisimai
36
60
  if c___[1]
37
61
  # Run the callback function specified with "c___" parameter of Sisimai.rise after reading
38
62
  # each email file in Maildir/ every time
39
- args = {'kind' => kind, 'mail' => r, 'path' => path, 'fact' => fact}
63
+ args = {'kind' => mail.kind, 'mail' => r, 'path' => path, 'fact' => fact}
40
64
  begin
41
65
  c___[1].call(args) if c___[1].is_a?(Proc)
42
66
  rescue StandardError => ce