sisimai 4.24.1 → 4.25.0

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
@@ -5,6 +5,13 @@ module Sisimai
5
5
  module Vacation
6
6
  # Imported from p5-Sisimail/lib/Sisimai/Reason/Vacation.pm
7
7
  class << self
8
+ Index = [
9
+ 'i am away on vacation',
10
+ 'i am away until',
11
+ 'i am out of the office',
12
+ 'i will be traveling for work on',
13
+ ]
14
+
8
15
  def text; return 'vacation'; end
9
16
  def description; return 'Email replied automatically due to a recipient is out of office'; end
10
17
 
@@ -14,14 +21,7 @@ module Sisimai
14
21
  # true: Matched
15
22
  def match(argv1)
16
23
  return nil unless argv1
17
- index = [
18
- 'i am away on vacation',
19
- 'i am away until',
20
- 'i am out of the office',
21
- 'i will be traveling for work on',
22
- ]
23
-
24
- return true if index.any? { |a| argv1.include?(a) }
24
+ return true if Index.any? { |a| argv1.include?(a) }
25
25
  return false
26
26
  end
27
27
 
@@ -16,6 +16,13 @@ module Sisimai
16
16
  module VirusDetected
17
17
  # Imported from p5-Sisimail/lib/Sisimai/Reason/VirusDetected.pm
18
18
  class << self
19
+ Index = [
20
+ 'it has a potentially executable attachment',
21
+ 'the message was rejected because it contains prohibited virus or spam content',
22
+ 'this form of attachment has been used by recent viruses or other malware',
23
+ 'your message was infected with a virus',
24
+ ]
25
+
19
26
  def text; return 'virusdetected'; end
20
27
  def description; return 'Email rejected due to a virus scanner on a destination host'; end
21
28
 
@@ -26,14 +33,7 @@ module Sisimai
26
33
  # @since 4.22.0
27
34
  def match(argv1)
28
35
  return nil unless argv1
29
- index = [
30
- 'it has a potentially executable attachment',
31
- 'the message was rejected because it contains prohibited virus or spam content',
32
- 'this form of attachment has been used by recent viruses or other malware',
33
- 'your message was infected with a virus',
34
- ]
35
-
36
- return true if index.any? { |a| argv1.include?(a) }
36
+ return true if Index.any? { |a| argv1.include?(a) }
37
37
  return false
38
38
  end
39
39
 
@@ -0,0 +1,142 @@
1
+ module Sisimai
2
+ # Sisimai::RFC1894 DSN field defined in RFC3464 (obsoletes RFC1894)
3
+ module RFC1894
4
+ # Imported from p5-Sisimail/lib/Sisimai/RFC1894.pm
5
+ class << self
6
+ FieldNames = [
7
+ # https://tools.ietf.org/html/rfc3464#section-2.2
8
+ # Some fields of a DSN apply to all of the delivery attempts described by
9
+ # that DSN. At most, these fields may appear once in any DSN. These fields
10
+ # are used to correlate the DSN with the original message transaction and
11
+ # to provide additional information which may be useful to gateways.
12
+ #
13
+ # The following fields (not defined in RFC 3464) are used in Sisimai
14
+ # - X-Original-Message-ID: <....> (GSuite)
15
+ #
16
+ # The following fields are not used in Sisimai:
17
+ # - Original-Envelope-Id
18
+ # - DSN-Gateway
19
+ %w[Reporting-MTA Received-From-MTA Arrival-Date X-Original-Message-ID],
20
+
21
+ # https://tools.ietf.org/html/rfc3464#section-2.3
22
+ # A DSN contains information about attempts to deliver a message to one or
23
+ # more recipients. The delivery information for any particular recipient is
24
+ # contained in a group of contiguous per-recipient fields.
25
+ # Each group of per-recipient fields is preceded by a blank line.
26
+ #
27
+ # The following fields (not defined in RFC 3464) are used in Sisimai
28
+ # - X-Actual-Recipient: RFC822; ....
29
+ #
30
+ # The following fields are not used in Sisimai:
31
+ # - Will-Retry-Until
32
+ # - Final-Log-ID
33
+ %w[Original-Recipient Final-Recipient Action Status Remote-MTA
34
+ Diagnostic-Code Last-Attempt-Date X-Actual-Recipient],
35
+ ].freeze
36
+
37
+ CapturesOn = {
38
+ 'addr' => %r/\A((?:Original|Final|X-Actual)-Recipient):[ ]*(.+?);[ ]*(.+)/,
39
+ 'code' => %r/\A(Diagnostic-Code):[ ]*(.+?);[ ]*(.*)/,
40
+ 'date' => %r/\A((?:Arrival|Last-Attempt)-Date):[ ]*(.+)/,
41
+ 'host' => %r/\A((?:Reporting|Received-From|Remote)-MTA):[ ]*(.+?);[ ]*(.+)/,
42
+ 'list' => %r/\A(Action):[ ]*(failed|delayed|delivered|relayed|expanded|expired|failure)/i,
43
+ 'stat' => %r/\A(Status):[ ]*([245][.]\d+[.]\d+)/,
44
+ 'text' => %r/\A(X-Original-Message-ID):[ ]*(.+)/,
45
+ #text: %r/\A(Original-Envelope-Id|Final-Log-ID):[ ]*(.+)/,
46
+ }.freeze
47
+
48
+ Correction = { action: { 'failure' => 'failed', 'expired' => 'delayed' } }
49
+ FieldGroup = {
50
+ 'original-recipient' => 'addr',
51
+ 'final-recipient' => 'addr',
52
+ 'x-actual-recipient' => 'addr',
53
+ 'diagnostic-code' => 'code',
54
+ 'arrival-date' => 'date',
55
+ 'last-attempt-date' => 'date',
56
+ 'received-from-mta' => 'host',
57
+ 'remote-mta' => 'host',
58
+ 'reporting-mta' => 'host',
59
+ 'action' => 'list',
60
+ 'status' => 'stat',
61
+ 'x-original-message-id' => 'text',
62
+ }.freeze
63
+
64
+ # Table to be converted to key name defined in Sisimai::Bite class
65
+ # @param [Symbol] group RFC822 Header group name
66
+ # @return [Array,Hash] RFC822 Header list
67
+ def FIELDTABLE
68
+ return {
69
+ 'action' => 'action',
70
+ 'arrival-date' => 'date',
71
+ 'diagnostic-code' => 'diagnosis',
72
+ 'final-recipient' => 'recipient',
73
+ 'last-attempt-date' => 'date',
74
+ 'original-recipient' => 'alias',
75
+ 'received-from-mta' => 'lhost',
76
+ 'remote-mta' => 'rhost',
77
+ 'reporting-mta' => 'rhost',
78
+ 'status' => 'status',
79
+ 'x-actual-recipient' => 'alias',
80
+ }
81
+ end
82
+
83
+ # Check the argument matches with a field defined in RFC3464
84
+ # @param [String] argv0 A line inlcuding field and value defined in RFC3464
85
+ # @return [Integer] 0: did not matched, 1,2: matched
86
+ # @since v4.25.0
87
+ def match(argv0 = '')
88
+ return nil if argv0.empty?
89
+ return 1 if FieldNames[0].any? { |a| argv0.start_with?(a) }
90
+ return 2 if FieldNames[1].any? { |a| argv0.start_with?(a) }
91
+ return nil
92
+ end
93
+
94
+ # Check the argument is including field defined in RFC3464 and return values
95
+ # @param [String] argv0 A line inlcuding field and value defined in RFC3464
96
+ # @return [Array] ['field-name', 'value-type', 'Value', 'field-group']
97
+ # @since v4.25.0
98
+ def field(argv0 = '')
99
+ return nil if argv0.empty?
100
+ group = FieldGroup[argv0.split(':',2).shift.downcase] || ''
101
+ match = []
102
+
103
+ return nil if group.empty?
104
+ return nil unless CapturesOn[group]
105
+
106
+ while cv = argv0.match(CapturesOn[group])
107
+ # Try to match with each pattern of Per-Message field, Per-Recipient field
108
+ # - 0: Field-Name
109
+ # - 1: Sub Type: RFC822, DNS, X-Unix, and so on)
110
+ # - 2: Value
111
+ # - 3: Field Group(addr, code, date, host, stat, text)
112
+ match[0] = cv[1].downcase
113
+ match[3] = group
114
+
115
+ if group == 'addr' || group == 'code' || group == 'host'
116
+ # - Final-Recipient: RFC822; kijitora@nyaan.jp
117
+ # - Diagnostic-Code: SMTP; 550 5.1.1 <kijitora@example.jp>... User Unknown
118
+ # - Remote-MTA: DNS; mx.example.jp
119
+ match[1] = cv[2].upcase
120
+ match[2] = group == 'host' ? cv[3].downcase : cv[3]
121
+ match[2] = '' if match[2] =~ /\A\s+\z/ # Remote-MTA: dns;
122
+ else
123
+ # - Action: failed
124
+ # - Status: 5.2.2
125
+ match[1] = ''
126
+ match[2] = group == 'date' ? cv[2] : cv[2].downcase
127
+
128
+ # Correct invalid value in Action field:
129
+ break unless group == 'list'
130
+ break unless Correction[:action].key?(match[2])
131
+ match[2] = Correction[:action][match[2]]
132
+ end
133
+ break
134
+ end
135
+ return nil if match.empty?
136
+ return match
137
+ end
138
+
139
+ end
140
+ end
141
+ end
142
+
@@ -27,6 +27,68 @@ module Sisimai
27
27
  error: %r/\A(?:[45]\d\d[ \t]+|[<][^@]+[@][^@]+[>]:?[ \t]+)/,
28
28
  command: %r/[ ](RCPT|MAIL|DATA)[ ]+command\b/,
29
29
  }.freeze
30
+ ReSkip = %r{(?>
31
+ \A[-]+=
32
+ |\A\s+\z
33
+ |\A\s*--
34
+ |\A\s+[=]\d+
35
+ |\Ahi[ ][!]
36
+ |content-(?:description|disposition|transfer-encoding|type):[ ]
37
+ |(?:name|charset)=
38
+ |--\z
39
+ |:[ ]--------
40
+ )
41
+ }x.freeze
42
+ ReStop = %r{(?:
43
+ \A[*][*][*][ ].+[ ].+[ ][*][*][*]
44
+ |\Acontent-type:[ ]message/delivery-status
45
+ |\Ahere[ ]is[ ]a[ ]copy[ ]of[ ]the[ ]first[ ]part[ ]of[ ]the[ ]message
46
+ |\Athe[ ]non-delivered[ ]message[ ]is[ ]attached[ ]to[ ]this[ ]message.
47
+ |\Areceived:[ \t]*
48
+ |\Areceived-from-mta:[ \t]*
49
+ |\Areporting-mta:[ \t]*
50
+ |\Areturn-path:[ \t]*
51
+ |\Aa[ ]copy[ ]of[ ]the[ ]original[ ]message[ ]below[ ]this[ ]line:
52
+ |attachment[ ]is[ ]a[ ]copy[ ]of[ ]the[ ]message
53
+ |below[ ]is[ ]a[ ]copy[ ]of[ ]the[ ]original[ ]message:
54
+ |below[ ]this[ ]line[ ]is[ ]a[ ]copy[ ]of[ ]the[ ]message
55
+ |message[ ]contains[ ].+[ ]file[ ]attachments
56
+ |message[ ]text[ ]follows:[ ]
57
+ |original[ ]message[ ]follows
58
+ |the[ ]attachment[ ]contains[ ]the[ ]original[ ]mail[ ]headers
59
+ |the[ ]first[ ]\d+[ ]lines[ ]
60
+ |unsent[ ]Message[ ]below
61
+ |your[ ]message[ ]reads[ ][(]in[ ]part[)]:
62
+ )
63
+ }x.freeze
64
+ ReAddr = %r{(?:
65
+ \A\s*
66
+ |\A["].+["]\s*
67
+ |\A[ \t]*Recipient:[ \t]*
68
+ |\A[ ]*Address:[ ]
69
+ |addressed[ ]to[ ]
70
+ |Could[ ]not[ ]be[ ]delivered[ ]to:[ ]
71
+ |delivered[ ]to[ ]+
72
+ |delivery[ ]failed:[ ]
73
+ |Did[ ]not[ ]reach[ ]the[ ]following[ ]recipient:[ ]
74
+ |Error-for:[ ]+
75
+ |Failed[ ]Recipient:[ ]
76
+ |Failed[ ]to[ ]deliver[ ]to[ ]
77
+ |Intended[ ]recipient:[ ]
78
+ |Mailbox[ ]is[ ]full:[ ]
79
+ |RCPT[ ]To:
80
+ |SMTP[ ]Server[ ][<].+[>][ ]rejected[ ]recipient[ ]
81
+ |The[ ]following[ ]recipients[ ]returned[ ]permanent[ ]errors:[ ]
82
+ |The[ ]following[ ]message[ ]to[ ]
83
+ |Unknown[ ]User:[ ]
84
+ |undeliverable[ ]to[ ]
85
+ |Undeliverable[ ]Address:[ ]*
86
+ |You[ ]sent[ ]mail[ ]to[ ]
87
+ |Your[ ]message[ ]to[ ]
88
+ )
89
+ ['"]?[<]?([^\s\n\r@=<>]+[@][-.0-9A-Za-z]+[.][0-9A-Za-z]+)[>]?['"]?
90
+ }xi.freeze
91
+
30
92
 
31
93
  def description; 'Fallback Module for MTAs'; end
32
94
  def smtpagent; 'RFC3464'; end
@@ -84,7 +146,7 @@ module Sisimai
84
146
  end
85
147
 
86
148
  if readcursor & Indicators[:'message-rfc822'] > 0
87
- # After "message/rfc822"
149
+ # Inside of the original message part
88
150
  if e.empty?
89
151
  blanklines += 1
90
152
  break if blanklines > 1
@@ -92,13 +154,13 @@ module Sisimai
92
154
  end
93
155
  rfc822list << e
94
156
  else
95
- # Before "message/rfc822"
157
+ # Error message part
96
158
  next unless readcursor & Indicators[:deliverystatus] > 0
97
159
  next if e.empty?
98
160
 
99
161
  v = dscontents[-1]
100
- if cv = e.match(/\A(?:Final|Original)-Recipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/) ||
101
- e.match(/\A(?:Final|Original)-Recipient:[ ]*([^ ]+)\z/)
162
+ if cv = e.match(/\A(?:Final|Original)-[Rr]ecipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/) ||
163
+ e.match(/\A(?:Final|Original)-[Rr]ecipient:[ ]*([^ ]+)\z/)
102
164
  # 2.3.2 Final-Recipient field
103
165
  # The Final-Recipient field indicates the recipient for which this set
104
166
  # of per-recipient fields applies. This field MUST be present in each
@@ -305,68 +367,6 @@ module Sisimai
305
367
  end
306
368
  break unless match > 0
307
369
 
308
- re_skip = %r{(?>
309
- \A[-]+=
310
- |\A\s+\z
311
- |\A\s*--
312
- |\A\s+[=]\d+
313
- |\Ahi[ ][!]
314
- |content-(?:description|disposition|transfer-encoding|type):[ ]
315
- |(?:name|charset)=
316
- |--\z
317
- |:[ ]--------
318
- )
319
- }x
320
- re_stop = %r{(?:
321
- \A[*][*][*][ ].+[ ].+[ ][*][*][*]
322
- |\Acontent-type:[ ]message/delivery-status
323
- |\Ahere[ ]is[ ]a[ ]copy[ ]of[ ]the[ ]first[ ]part[ ]of[ ]the[ ]message
324
- |\Athe[ ]non-delivered[ ]message[ ]is[ ]attached[ ]to[ ]this[ ]message.
325
- |\Areceived:[ \t]*
326
- |\Areceived-from-mta:[ \t]*
327
- |\Areporting-mta:[ \t]*
328
- |\Areturn-path:[ \t]*
329
- |\Aa[ ]copy[ ]of[ ]the[ ]original[ ]message[ ]below[ ]this[ ]line:
330
- |attachment[ ]is[ ]a[ ]copy[ ]of[ ]the[ ]message
331
- |below[ ]is[ ]a[ ]copy[ ]of[ ]the[ ]original[ ]message:
332
- |below[ ]this[ ]line[ ]is[ ]a[ ]copy[ ]of[ ]the[ ]message
333
- |message[ ]contains[ ].+[ ]file[ ]attachments
334
- |message[ ]text[ ]follows:[ ]
335
- |original[ ]message[ ]follows
336
- |the[ ]attachment[ ]contains[ ]the[ ]original[ ]mail[ ]headers
337
- |the[ ]first[ ]\d+[ ]lines[ ]
338
- |unsent[ ]Message[ ]below
339
- |your[ ]message[ ]reads[ ][(]in[ ]part[)]:
340
- )
341
- }x
342
- re_addr = %r{(?:
343
- \A\s*
344
- |\A["].+["]\s*
345
- |\A[ \t]*Recipient:[ \t]*
346
- |\A[ ]*Address:[ ]
347
- |addressed[ ]to[ ]
348
- |Could[ ]not[ ]be[ ]delivered[ ]to:[ ]
349
- |delivered[ ]to[ ]+
350
- |delivery[ ]failed:[ ]
351
- |Did[ ]not[ ]reach[ ]the[ ]following[ ]recipient:[ ]
352
- |Error-for:[ ]+
353
- |Failed[ ]Recipient:[ ]
354
- |Failed[ ]to[ ]deliver[ ]to[ ]
355
- |Intended[ ]recipient:[ ]
356
- |Mailbox[ ]is[ ]full:[ ]
357
- |RCPT[ ]To:
358
- |SMTP[ ]Server[ ][<].+[>][ ]rejected[ ]recipient[ ]
359
- |The[ ]following[ ]recipients[ ]returned[ ]permanent[ ]errors:[ ]
360
- |The[ ]following[ ]message[ ]to[ ]
361
- |Unknown[ ]User:[ ]
362
- |undeliverable[ ]to[ ]
363
- |Undeliverable[ ]Address:[ ]*
364
- |You[ ]sent[ ]mail[ ]to[ ]
365
- |Your[ ]message[ ]to[ ]
366
- )
367
- ['"]?[<]?([^\s\n\r@=<>]+[@][-.0-9A-Za-z]+[.][0-9A-Za-z]+)[>]?['"]?
368
- }xi
369
-
370
370
  b = dscontents[-1]
371
371
  hasdivided = mbody.split("\n")
372
372
  while e = hasdivided.shift do
@@ -374,13 +374,13 @@ module Sisimai
374
374
  break if e.start_with?('__END_OF_EMAIL_MESSAGE__')
375
375
  d = e.downcase
376
376
  break if d =~ MarkingsOf[:rfc822]
377
- break if d =~ re_stop
377
+ break if d =~ ReStop
378
378
 
379
379
  next if e.empty?
380
- next if d =~ re_skip
380
+ next if d =~ ReSkip
381
381
  next if e.start_with?('*')
382
382
 
383
- if cv = e.match(re_addr)
383
+ if cv = e.match(ReAddr)
384
384
  # May be an email address
385
385
  x = b['recipient'] || ''
386
386
  y = Sisimai::Address.s3s4(cv[1])
@@ -451,7 +451,7 @@ module Sisimai
451
451
  e['agent'] = self.smtpagent
452
452
  end
453
453
 
454
- e['status'] ||= Sisimai::SMTP::Status.find(e['diagnosis'])
454
+ e['status'] ||= Sisimai::SMTP::Status.find(e['diagnosis']) || ''
455
455
  if cv = e['diagnosis'].match(MarkingsOf[:command])
456
456
  e['command'] = cv[1]
457
457
  end
@@ -7,11 +7,11 @@ module Sisimai
7
7
  MarkingsOf = { :boundary => %r/\A__SISIMAI_PSEUDO_BOUNDARY__\z/ }
8
8
  AutoReply1 = {
9
9
  # http://www.iana.org/assignments/auto-submitted-keywords/auto-submitted-keywords.xhtml
10
- :'auto-submitted' => %r/\Aauto-(?:generated|replied|notified)/,
10
+ 'auto-submitted' => %r/\Aauto-(?:generated|replied|notified)/,
11
11
  # https://msdn.microsoft.com/en-us/library/ee219609(v=exchg.80).aspx
12
- :'x-auto-response-suppress' => %r/(?:oof|autoreply)/,
13
- :'precedence' => %r/\Aauto_reply\z/,
14
- :'subject' => %r/\A(?>
12
+ 'x-auto-response-suppress' => %r/(?:oof|autoreply)/,
13
+ 'precedence' => %r/\Aauto_reply\z/,
14
+ 'subject' => %r/\A(?>
15
15
  auto:
16
16
  |auto[ ]response:
17
17
  |automatic[ ]reply:
@@ -20,13 +20,13 @@ module Sisimai
20
20
  /x,
21
21
  }.freeze
22
22
  Excludings = {
23
- :subject => %r/(?:
23
+ 'subject' => %r/(?:
24
24
  security[ ]information[ ]for # sudo
25
25
  |mail[ ]failure[ ][-] # Exim
26
26
  )
27
27
  /x,
28
- :from => %r/(?:root|postmaster|mailer-daemon)[@]/,
29
- :to => %r/root[@]/,
28
+ 'from' => %r/(?:root|postmaster|mailer-daemon)[@]/,
29
+ 'to' => %r/root[@]/,
30
30
  }.freeze
31
31
  SubjectSet = %r{\A(?>
32
32
  (?:.+?)?Re:
@@ -35,11 +35,11 @@ module Sisimai
35
35
  |Out[ ]of[ ]Office:
36
36
  )
37
37
  [ ]*(.+)\z
38
- }xi
38
+ }xi.freeze
39
39
 
40
40
  def description; 'Detector for auto replied message'; end
41
41
  def smtpagent; 'RFC3834'; end
42
- def headerlist; return %w[Auto-Submitted Precedence X-Auto-Response-Suppress]; end
42
+ def headerlist; return %w[auto-submitted precedence x-auto-response-suppress]; end
43
43
 
44
44
  # Detect auto reply message as RFC3834
45
45
  # @param [Hash] mhead Message header of a bounce email
@@ -59,9 +59,9 @@ module Sisimai
59
59
  # DETECT_EXCLUSION_MESSAGE
60
60
  Excludings.each_key do |e|
61
61
  # Exclude message from root@
62
- next unless mhead.key?(e.to_s)
63
- next unless mhead[e.to_s]
64
- next unless mhead[e.to_s].downcase =~ Excludings[e]
62
+ next unless mhead.key?(e)
63
+ next unless mhead[e]
64
+ next unless mhead[e].downcase =~ Excludings[e]
65
65
  leave = 1
66
66
  break
67
67
  end
@@ -70,9 +70,9 @@ module Sisimai
70
70
  # DETECT_AUTO_REPLY_MESSAGE
71
71
  AutoReply1.each_key do |e|
72
72
  # RFC3834 Auto-Submitted and other headers
73
- next unless mhead.key?(e.to_s)
74
- next unless mhead[e.to_s]
75
- next unless mhead[e.to_s].downcase =~ AutoReply1[e]
73
+ next unless mhead.key?(e)
74
+ next unless mhead[e]
75
+ next unless mhead[e].downcase =~ AutoReply1[e]
76
76
  match += 1
77
77
  break
78
78
  end