sisimai 5.1.0 → 5.2.0

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 (192) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake-test.yml +1 -1
  3. data/ChangeLog.md +102 -0
  4. data/Makefile +4 -2
  5. data/README-JA.md +23 -16
  6. data/README.md +22 -15
  7. data/lib/sisimai/arf.rb +121 -210
  8. data/lib/sisimai/fact.rb +208 -158
  9. data/lib/sisimai/lda.rb +98 -0
  10. data/lib/sisimai/lhost/activehunter.rb +1 -1
  11. data/lib/sisimai/lhost/amazonses.rb +185 -301
  12. data/lib/sisimai/lhost/apachejames.rb +48 -51
  13. data/lib/sisimai/lhost/biglobe.rb +1 -2
  14. data/lib/sisimai/lhost/courier.rb +10 -8
  15. data/lib/sisimai/lhost/domino.rb +25 -25
  16. data/lib/sisimai/lhost/dragonfly.rb +3 -4
  17. data/lib/sisimai/lhost/einsundeins.rb +3 -4
  18. data/lib/sisimai/lhost/exchange2003.rb +6 -8
  19. data/lib/sisimai/lhost/exchange2007.rb +111 -101
  20. data/lib/sisimai/lhost/exim.rb +232 -242
  21. data/lib/sisimai/lhost/ezweb.rb +43 -51
  22. data/lib/sisimai/lhost/fml.rb +2 -3
  23. data/lib/sisimai/lhost/gmail.rb +32 -28
  24. data/lib/sisimai/lhost/gmx.rb +4 -16
  25. data/lib/sisimai/lhost/googlegroups.rb +9 -8
  26. data/lib/sisimai/lhost/googleworkspace.rb +94 -0
  27. data/lib/sisimai/lhost/imailserver.rb +7 -16
  28. data/lib/sisimai/lhost/interscanmss.rb +1 -1
  29. data/lib/sisimai/lhost/kddi.rb +3 -4
  30. data/lib/sisimai/lhost/mailfoundry.rb +2 -5
  31. data/lib/sisimai/lhost/mailmarshalsmtp.rb +1 -2
  32. data/lib/sisimai/lhost/messagingserver.rb +14 -13
  33. data/lib/sisimai/lhost/mfilter.rb +4 -3
  34. data/lib/sisimai/lhost/notes.rb +2 -4
  35. data/lib/sisimai/lhost/opensmtpd.rb +2 -2
  36. data/lib/sisimai/lhost/postfix.rb +25 -27
  37. data/lib/sisimai/lhost/qmail.rb +130 -106
  38. data/lib/sisimai/lhost/sendmail.rb +19 -18
  39. data/lib/sisimai/lhost/v5sendmail.rb +88 -60
  40. data/lib/sisimai/lhost/verizon.rb +2 -2
  41. data/lib/sisimai/lhost/x1.rb +1 -1
  42. data/lib/sisimai/lhost/x2.rb +1 -2
  43. data/lib/sisimai/lhost/x3.rb +2 -2
  44. data/lib/sisimai/lhost/x6.rb +1 -1
  45. data/lib/sisimai/lhost/zoho.rb +2 -2
  46. data/lib/sisimai/lhost.rb +18 -21
  47. data/lib/sisimai/message.rb +93 -146
  48. data/lib/sisimai/order.rb +21 -77
  49. data/lib/sisimai/reason/authfailure.rb +1 -4
  50. data/lib/sisimai/reason/badreputation.rb +2 -2
  51. data/lib/sisimai/reason/blocked.rb +7 -10
  52. data/lib/sisimai/reason/contenterror.rb +7 -1
  53. data/lib/sisimai/reason/exceedlimit.rb +1 -4
  54. data/lib/sisimai/reason/failedstarttls.rb +42 -0
  55. data/lib/sisimai/reason/filtered.rb +5 -4
  56. data/lib/sisimai/reason/hasmoved.rb +1 -2
  57. data/lib/sisimai/reason/hostunknown.rb +3 -3
  58. data/lib/sisimai/reason/mailboxfull.rb +2 -4
  59. data/lib/sisimai/reason/mailererror.rb +1 -2
  60. data/lib/sisimai/reason/mesgtoobig.rb +2 -4
  61. data/lib/sisimai/reason/norelaying.rb +2 -3
  62. data/lib/sisimai/reason/notaccept.rb +2 -3
  63. data/lib/sisimai/reason/notcompliantrfc.rb +10 -4
  64. data/lib/sisimai/reason/rejected.rb +1 -1
  65. data/lib/sisimai/reason/requireptr.rb +2 -2
  66. data/lib/sisimai/reason/securityerror.rb +1 -3
  67. data/lib/sisimai/reason/spamdetected.rb +6 -8
  68. data/lib/sisimai/reason/speeding.rb +1 -2
  69. data/lib/sisimai/reason/suppressed.rb +36 -0
  70. data/lib/sisimai/reason/suspend.rb +1 -3
  71. data/lib/sisimai/reason/systemerror.rb +5 -0
  72. data/lib/sisimai/reason/toomanyconn.rb +1 -2
  73. data/lib/sisimai/reason/userunknown.rb +1 -1
  74. data/lib/sisimai/reason/virusdetected.rb +5 -6
  75. data/lib/sisimai/reason.rb +77 -73
  76. data/lib/sisimai/rfc1123.rb +152 -0
  77. data/lib/sisimai/rfc1894.rb +102 -62
  78. data/lib/sisimai/rfc2045.rb +2 -1
  79. data/lib/sisimai/rfc3464/thirdparty.rb +102 -0
  80. data/lib/sisimai/rfc3464.rb +222 -343
  81. data/lib/sisimai/rfc3834.rb +1 -1
  82. data/lib/sisimai/rfc5322.rb +7 -17
  83. data/lib/sisimai/rfc791.rb +69 -0
  84. data/lib/sisimai/rhost/aol.rb +36 -0
  85. data/lib/sisimai/rhost/apple.rb +5 -2
  86. data/lib/sisimai/rhost/cox.rb +3 -2
  87. data/lib/sisimai/rhost/facebook.rb +100 -0
  88. data/lib/sisimai/rhost/franceptt.rb +3 -2
  89. data/lib/sisimai/rhost/godaddy.rb +3 -2
  90. data/lib/sisimai/rhost/google.rb +19 -17
  91. data/lib/sisimai/rhost/gsuite.rb +42 -0
  92. data/lib/sisimai/rhost/iua.rb +3 -3
  93. data/lib/sisimai/rhost/kddi.rb +3 -2
  94. data/lib/sisimai/rhost/messagelabs.rb +37 -0
  95. data/lib/sisimai/rhost/microsoft.rb +56 -49
  96. data/lib/sisimai/rhost/mimecast.rb +29 -27
  97. data/lib/sisimai/rhost/nttdocomo.rb +4 -3
  98. data/lib/sisimai/rhost/outlook.rb +36 -0
  99. data/lib/sisimai/rhost/spectrum.rb +3 -2
  100. data/lib/sisimai/rhost/tencent.rb +3 -2
  101. data/lib/sisimai/rhost/yahooinc.rb +4 -3
  102. data/lib/sisimai/rhost.rb +69 -39
  103. data/lib/sisimai/smtp/command.rb +31 -21
  104. data/lib/sisimai/smtp/failure.rb +103 -0
  105. data/lib/sisimai/smtp/reply.rb +29 -25
  106. data/lib/sisimai/smtp/status.rb +36 -19
  107. data/lib/sisimai/smtp/transcript.rb +15 -15
  108. data/lib/sisimai/string.rb +0 -46
  109. data/lib/sisimai/version.rb +1 -1
  110. data/set-of-emails/maildir/bsd/lhost-postfix-30.eml +81 -81
  111. data/set-of-emails/maildir/bsd/{lhost-aol-03.eml → rhost-aol-03.eml} +1264 -1264
  112. data/set-of-emails/maildir/bsd/{lhost-aol-04.eml → rhost-aol-04.eml} +1260 -1260
  113. data/set-of-emails/maildir/bsd/{lhost-aol-05.eml → rhost-aol-05.eml} +105 -105
  114. data/set-of-emails/maildir/bsd/{lhost-aol-06.eml → rhost-aol-06.eml} +105 -105
  115. data/set-of-emails/maildir/bsd/rhost-gsuite-01.eml +189 -0
  116. data/set-of-emails/maildir/bsd/rhost-gsuite-02.eml +180 -0
  117. data/set-of-emails/maildir/bsd/rhost-gsuite-03.eml +251 -0
  118. data/set-of-emails/maildir/bsd/rhost-gsuite-04.eml +211 -0
  119. data/set-of-emails/maildir/bsd/rhost-gsuite-05.eml +226 -0
  120. data/set-of-emails/maildir/bsd/rhost-gsuite-06.eml +257 -0
  121. data/set-of-emails/maildir/bsd/rhost-gsuite-07.eml +289 -0
  122. data/set-of-emails/maildir/bsd/rhost-gsuite-08.eml +231 -0
  123. data/set-of-emails/maildir/bsd/rhost-gsuite-09.eml +231 -0
  124. data/set-of-emails/maildir/bsd/rhost-gsuite-10.eml +254 -0
  125. data/set-of-emails/maildir/bsd/rhost-gsuite-11.eml +228 -0
  126. data/set-of-emails/maildir/bsd/rhost-gsuite-12.eml +271 -0
  127. data/set-of-emails/maildir/bsd/rhost-gsuite-13.eml +261 -0
  128. data/set-of-emails/maildir/bsd/rhost-gsuite-14.eml +273 -0
  129. data/set-of-emails/maildir/bsd/rhost-gsuite-15.eml +229 -0
  130. data/set-of-emails/maildir/bsd/{lhost-messagelabs-01.eml → rhost-messagelabs-01.eml} +93 -93
  131. data/set-of-emails/maildir/bsd/rhost-outlook-01.eml +72 -0
  132. data/set-of-emails/maildir/bsd/rhost-outlook-02.eml +72 -0
  133. data/set-of-emails/maildir/bsd/rhost-outlook-03.eml +72 -0
  134. data/set-of-emails/maildir/bsd/rhost-outlook-04.eml +79 -0
  135. data/set-of-emails/maildir/bsd/rhost-outlook-06.eml +75 -0
  136. data/set-of-emails/maildir/bsd/rhost-outlook-07.eml +70 -0
  137. data/set-of-emails/maildir/bsd/rhost-outlook-08.eml +70 -0
  138. data/set-of-emails/maildir/bsd/rhost-outlook-09.eml +56 -0
  139. data/set-of-emails/maildir/tmp/arf-22.eml +49 -0
  140. data/set-of-emails/maildir/tmp/arf-23.eml +49 -0
  141. data/set-of-emails/maildir/tmp/arf-24.eml +50 -0
  142. data/set-of-emails/maildir/tmp/lhost-exim-07.eml +28 -0
  143. metadata +73 -56
  144. data/lib/sisimai/lhost/amavis.rb +0 -163
  145. data/lib/sisimai/lhost/amazonworkmail.rb +0 -127
  146. data/lib/sisimai/lhost/aol.rb +0 -125
  147. data/lib/sisimai/lhost/barracuda.rb +0 -92
  148. data/lib/sisimai/lhost/bigfoot.rb +0 -125
  149. data/lib/sisimai/lhost/facebook.rb +0 -188
  150. data/lib/sisimai/lhost/gsuite.rb +0 -194
  151. data/lib/sisimai/lhost/mailru.rb +0 -214
  152. data/lib/sisimai/lhost/mcafee.rb +0 -109
  153. data/lib/sisimai/lhost/messagelabs.rb +0 -120
  154. data/lib/sisimai/lhost/mxlogic.rb +0 -198
  155. data/lib/sisimai/lhost/office365.rb +0 -252
  156. data/lib/sisimai/lhost/outlook.rb +0 -129
  157. data/lib/sisimai/lhost/powermta.rb +0 -118
  158. data/lib/sisimai/lhost/receivingses.rb +0 -126
  159. data/lib/sisimai/lhost/sendgrid.rb +0 -150
  160. data/lib/sisimai/lhost/surfcontrol.rb +0 -105
  161. data/lib/sisimai/lhost/x4.rb +0 -269
  162. data/lib/sisimai/lhost/x5.rb +0 -112
  163. data/lib/sisimai/lhost/yahoo.rb +0 -102
  164. data/lib/sisimai/lhost/yandex.rb +0 -118
  165. data/lib/sisimai/mda.rb +0 -121
  166. data/lib/sisimai/smtp/error.rb +0 -119
  167. /data/set-of-emails/maildir/bsd/{lhost-googlegroups-15.eml → lhost-googleworkspace-01.eml} +0 -0
  168. /data/set-of-emails/maildir/bsd/{lhost-x4-08.eml → lhost-x2-06.eml} +0 -0
  169. /data/set-of-emails/maildir/bsd/{lhost-gsuite-01.eml → rfc3464-51.eml} +0 -0
  170. /data/set-of-emails/maildir/bsd/{lhost-gsuite-03.eml → rfc3464-52.eml} +0 -0
  171. /data/set-of-emails/maildir/bsd/{lhost-gsuite-04.eml → rfc3464-53.eml} +0 -0
  172. /data/set-of-emails/maildir/bsd/{lhost-gsuite-05.eml → rfc3464-54.eml} +0 -0
  173. /data/set-of-emails/maildir/bsd/{lhost-gsuite-06.eml → rfc3464-55.eml} +0 -0
  174. /data/set-of-emails/maildir/bsd/{lhost-gsuite-07.eml → rfc3464-56.eml} +0 -0
  175. /data/set-of-emails/maildir/bsd/{lhost-gsuite-08.eml → rfc3464-57.eml} +0 -0
  176. /data/set-of-emails/maildir/bsd/{lhost-gsuite-09.eml → rfc3464-58.eml} +0 -0
  177. /data/set-of-emails/maildir/bsd/{lhost-gsuite-10.eml → rfc3464-59.eml} +0 -0
  178. /data/set-of-emails/maildir/bsd/{lhost-gsuite-11.eml → rfc3464-60.eml} +0 -0
  179. /data/set-of-emails/maildir/bsd/{lhost-gsuite-12.eml → rfc3464-61.eml} +0 -0
  180. /data/set-of-emails/maildir/bsd/{lhost-gsuite-13.eml → rfc3464-62.eml} +0 -0
  181. /data/set-of-emails/maildir/bsd/{lhost-gsuite-14.eml → rfc3464-63.eml} +0 -0
  182. /data/set-of-emails/maildir/bsd/{lhost-gsuite-15.eml → rfc3464-64.eml} +0 -0
  183. /data/set-of-emails/maildir/bsd/{lhost-gsuite-02.eml → rfc3464-65.eml} +0 -0
  184. /data/set-of-emails/maildir/bsd/{lhost-aol-01.eml → rhost-aol-01.eml} +0 -0
  185. /data/set-of-emails/maildir/bsd/{lhost-aol-02.eml → rhost-aol-02.eml} +0 -0
  186. /data/set-of-emails/maildir/bsd/{lhost-facebook-03.eml → rhost-facebook-03.eml} +0 -0
  187. /data/set-of-emails/maildir/bsd/{lhost-facebook-04.eml → rhost-facebook-04.eml} +0 -0
  188. /data/set-of-emails/maildir/bsd/{lhost-messagelabs-02.eml → rhost-messagelabs-02.eml} +0 -0
  189. /data/set-of-emails/maildir/bsd/{lhost-messagelabs-03.eml → rhost-messagelabs-03.eml} +0 -0
  190. /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-37.eml +0 -0
  191. /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-38.eml +0 -0
  192. /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-39.eml +0 -0
@@ -4,6 +4,7 @@ module Sisimai::Lhost
4
4
  module Sendmail
5
5
  class << self
6
6
  require 'sisimai/lhost'
7
+ require 'sisimai/rfc1123'
7
8
  require 'sisimai/smtp/reply'
8
9
  require 'sisimai/smtp/status'
9
10
  require 'sisimai/smtp/command'
@@ -55,24 +56,25 @@ module Sisimai::Lhost
55
56
  readslices << e # Save the current line for the next loop
56
57
 
57
58
  if readcursor == 0
58
- # Beginning of the bounce message or message/delivery-status part
59
+ # Beginning of the bounce message or the message/delivery-status part
59
60
  readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
60
61
  next
61
62
  end
62
63
  next if (readcursor & Indicators[:deliverystatus]) == 0
63
64
  next if e.empty?
64
65
 
65
- if f = Sisimai::RFC1894.match(e)
66
+ f = Sisimai::RFC1894.match(e)
67
+ if f > 0
66
68
  # "e" matched with any field defined in RFC3464
67
69
  o = Sisimai::RFC1894.field(e) || next
68
70
  v = dscontents[-1]
69
71
 
70
- if o[-1] == 'addr'
72
+ if o[3] == 'addr'
71
73
  # Final-Recipient: rfc822; kijitora@example.jp
72
74
  # X-Actual-Recipient: rfc822; kijitora@example.co.jp
73
75
  if o[0] == 'final-recipient'
74
76
  # Final-Recipient: rfc822; kijitora@example.jp
75
- if v['recipient']
77
+ if v["recipient"] != ""
76
78
  # There are multiple recipient addresses in the message body.
77
79
  dscontents << Sisimai::Lhost.DELIVERYSTATUS
78
80
  v = dscontents[-1]
@@ -83,16 +85,17 @@ module Sisimai::Lhost
83
85
  # X-Actual-Recipient: rfc822; kijitora@example.co.jp
84
86
  v['alias'] = o[2]
85
87
  end
86
- elsif o[-1] == 'code'
88
+ elsif o[3] == 'code'
87
89
  # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
88
90
  v['spec'] = o[1]
89
91
  v['diagnosis'] = o[2]
90
92
  else
91
93
  # Other DSN fields defined in RFC3464
92
94
  next unless fieldtable[o[0]]
95
+ next if o[3] == "host" && Sisimai::RFC1123.is_internethost(o[2]) == false
93
96
  v[fieldtable[o[0]]] = o[2]
94
97
 
95
- next unless f
98
+ next unless f == 1
96
99
  permessage[fieldtable[o[0]]] = o[2]
97
100
  end
98
101
  else
@@ -109,15 +112,15 @@ module Sisimai::Lhost
109
112
  # Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
110
113
  unless e.start_with?(' ')
111
114
  if e.start_with?('>>> ')
112
- # >>> DATA
113
- thecommand = Sisimai::SMTP::Command.find(e)
115
+ # >>> DATA (Client Command)
116
+ thecommand = Sisimai::SMTP::Command.find(e) if thecommand.empty?
114
117
 
115
118
  elsif e.start_with?('<<< ')
116
- # <<< Response
119
+ # <<< Response from the SMTP server
117
120
  cv = e[4, e.size - 4]
118
121
  esmtpreply << cv unless esmtpreply.index(cv)
119
122
  else
120
- # Detect SMTP session error or connection error
123
+ # Detect an SMTP session error or a connection error
121
124
  next if sessionerr
122
125
  if e.start_with?(StartingOf[:error][0])
123
126
  # ----- Transcript of session follows -----
@@ -134,8 +137,8 @@ module Sisimai::Lhost
134
137
  # ----- Transcript of session follows -----
135
138
  # Message could not be delivered for too long
136
139
  # Message will be deleted from queue
137
- cr = Sisimai::SMTP::Reply.find(e) || ''
138
- cs = Sisimai::SMTP::Status.find(e) || ''
140
+ cr = Sisimai::SMTP::Reply.find(e)
141
+ cs = Sisimai::SMTP::Status.find(e)
139
142
 
140
143
  if cr.size + cs.size > 7
141
144
  # 550 5.1.2 <kijitora@example.org>... Message
@@ -167,13 +170,12 @@ module Sisimai::Lhost
167
170
 
168
171
  dscontents.each do |e|
169
172
  # Set default values if each value is empty.
170
- e['diagnosis'] ||= ''
171
173
  permessage.each_key { |a| e[a] ||= permessage[a] || '' }
172
174
 
173
175
  if anotherset['diagnosis']
174
176
  # Copy alternative error message
175
177
  e['diagnosis'] = anotherset['diagnosis'] if e['diagnosis'].start_with?(' ')
176
- e['diagnosis'] = anotherset['diagnosis'] if e['diagnosis'].=~ /\A\d+\z/
178
+ e['diagnosis'] = anotherset['diagnosis'] if e['diagnosis'] =~ /\A\d+\z/
177
179
  e['diagnosis'] = anotherset['diagnosis'] if e['diagnosis'].empty?
178
180
  end
179
181
 
@@ -188,10 +190,9 @@ module Sisimai::Lhost
188
190
  end
189
191
 
190
192
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
191
- e['command'] ||= thecommand || Sisimai::SMTP::Command.find(e['diagnosis']) || ''
192
- if e['command'].empty?
193
- e['command'] = 'EHLO' unless esmtpreply.empty?
194
- end
193
+ e["command"] = thecommand if e["command"].empty?
194
+ e["command"] = Sisimai::SMTP::Command.find(e['diagnosis']) if e["command"].empty?
195
+ e["command"] = "EHLO" if e["command"].empty? && esmtpreply.size > 0
195
196
 
196
197
  while true
197
198
  # Check alternative status code and override it
@@ -25,7 +25,7 @@ module Sisimai::Lhost
25
25
  # savemail.c:497| while (fgets(buf, sizeof buf, xfile) != NULL)
26
26
  # savemail.c:498| putline(buf, fp, m);
27
27
  # savemail.c:499| (void) fclose(xfile);
28
- error: [' while talking to '],
28
+ error: ['While talking to '],
29
29
  message: ['----- Transcript of session follows -----'],
30
30
  }.freeze
31
31
 
@@ -41,15 +41,15 @@ module Sisimai::Lhost
41
41
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
42
42
  return nil unless emailparts[1].size > 0
43
43
 
44
+ require 'sisimai/rfc1123'
44
45
  require 'sisimai/smtp/command'
45
46
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
46
47
  bodyslices = emailparts[0].split("\n")
47
48
  readcursor = 0 # (Integer) Points the current cursor position
48
49
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
49
- anotherset = {} # (Hash) Another error information
50
- responding = [] # (Array) Responses from remote server
51
- commandset = [] # (Array) SMTP command which is sent to remote server
52
- errorindex = -1 # (Integer)
50
+ anotherone = {} # (Hash) Another error information
51
+ remotehost = "" # The last remote hostname
52
+ curcommand = "" # The last SMTP command
53
53
  v = nil
54
54
 
55
55
  while e = bodyslices.shift do
@@ -70,75 +70,103 @@ module Sisimai::Lhost
70
70
  # 550 <kijitora@example.org>... User unknown
71
71
  # 421 example.org (smtp)... Deferred: Connection timed out during user open with example.org
72
72
  v = dscontents[-1]
73
+ curcommand = Sisimai::SMTP::Command.find(e) if e.start_with?(">>> ")
73
74
 
74
- if e.start_with?('5', '4') && Sisimai::String.aligned(e, [' <', '@', '>...'])
75
+ if Sisimai::String.aligned(e, [' <', '@', '>...']) || e.upcase.include?(">>> RCPT TO:")
75
76
  # 550 <kijitora@example.org>... User unknown
76
- if v['recipient']
77
- # There are multiple recipient addresses in the message body.
78
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
79
- v = dscontents[-1]
80
- end
81
- p1 = e.index('<', 0)
82
- p2 = e.index('>...')
83
- v['recipient'] = e[p1 + 1, p2 - p1 - 1]
84
- v['diagnosis'] = e[p2 + 5, e.size]
85
-
86
- # Concatenate the response of the server and error message
87
- v['diagnosis'] << ': ' << responding[recipients] if responding[recipients]
88
- recipients += 1
89
-
90
- elsif e.start_with?('>>> ')
91
77
  # >>> RCPT To:<kijitora@example.org>
92
- cv = Sisimai::SMTP::Command.find(e); commandset[recipients] = cv if cv
93
-
94
- elsif e.start_with?('<<< ')
95
- # <<< Response
96
- # <<< 501 <shironeko@example.co.jp>... no access from mail server [192.0.2.55] which is an open relay.
97
- # <<< 550 Requested User Mailbox not found. No such user here.
98
- responding[recipients] = e[4, e.size]
78
+ p0 = e.index(" ")
79
+ p1 = e.index("<", p0)
80
+ p2 = e.index(">", p1)
81
+ cv = Sisimai::Address.s3s4(e[p1, p2 - p1 + 1])
82
+
83
+ if remotehost == ""
84
+ # Keep error messages before "While talking to ..." line
85
+ anotherone[recipients] ||= ""; anotherone[recipients] << " " << e
86
+ next
87
+ end
99
88
 
89
+ if cv == v["recipient"] || (curcommand == "MAIL" && e.start_with?("<<< "))
90
+ # The recipient address is the same address with the last appeared address
91
+ # like "550 <mikeneko@example.co.jp>... User unknown"
92
+ # Append this line to the string which is keeping error messages
93
+ v["diagnosis"] << " " << e
94
+ v["replycode"] = Sisimai::SMTP::Reply.find(e)
95
+ curcommand = ""
96
+ else
97
+ # The recipient address in this line differs from the last appeared address
98
+ # or is the first recipient address in this bounce message
99
+ if v["recipient"] != ""
100
+ # There are multiple recipient addresses in the message body.
101
+ dscontents << Sisimai::Lhost.DELIVERYSTATUS
102
+ v = dscontents[-1]
103
+ end
104
+ recipients += 1
105
+ v["recipient"] = cv
106
+ v["rhost"] = remotehost
107
+ v["replycode"] = Sisimai::SMTP::Reply.find(e)
108
+ v["diagnosis"] << " " << e
109
+ v["command"] = curcommand if v["command"].empty?
110
+ end
100
111
  else
101
- # Detect SMTP session error or connection error
102
- next if v['sessionerr']
103
-
112
+ # This line does not include a recipient address
104
113
  if e.include?(StartingOf[:error][0])
105
- # ----- Transcript of session follows -----
106
114
  # ... while talking to mta.example.org.:
107
- v['sessionerr'] = true
108
- next
109
- end
110
-
111
- if e.start_with?('4', '5') && e.include?('... ')
112
- # 421 example.org (smtp)... Deferred: Connection timed out during user open with example.org
113
- anotherset['replycode'] = e[0, 3]
114
- anotherset['diagnosis'] = e[e.index('... ') + 4, e.size]
115
+ cv = Sisimai::RFC1123.find(e)
116
+ remotehost = cv if Sisimai::RFC1123.is_internethost(cv)
117
+ else
118
+ # Append this line into the error message string
119
+ if e.start_with?(">>> ", "<<< ")
120
+ # >>> DATA
121
+ # <<< 550 Your E-Mail is redundant. You cannot send E-Mail to yourself (shironeko@example.jp).
122
+ # >>> QUIT
123
+ # <<< 421 dns.example.org Sorry, unable to contact destination SMTP daemon.
124
+ # <<< 550 Requested User Mailbox not found. No such user here.
125
+ v["diagnosis"] << " " << e
126
+ else
127
+ # 421 Other error message
128
+ anotherone[recipients] ||= ""; anotherone[recipients] << " " << e
129
+ end
115
130
  end
116
131
  end
117
132
  end
118
133
 
119
- p1 = emailparts[1].index("\nTo: ") || -1
120
- p2 = emailparts[1].index("\n", p1 + 6) || -1
121
- if recipients == 0 && p1 > 0
122
- # Get the recipient address from "To:" header at the original message
123
- dscontents[0]['recipient'] = Sisimai::Address.s3s4(emailparts[1][p1, p2 - p1 - 5])
124
- recipients = 1
134
+ if recipients == 0
135
+ # There is no recipient address in the error message
136
+ anotherone.each_key do |e|
137
+ # Try to pick an recipient address, a reply code, and error messages
138
+ cv = Sisimai::Address.s3s4(anotherone[e]); next unless Sisimai::Address.is_emailaddress(cv)
139
+ cr = Sisimai::SMTP::Reply.find(anotherone[e])
140
+
141
+ dscontents[e]["recipient"] = cv
142
+ dscontents[e]["replycode"] = cr
143
+ dscontents[e]["diagnosis"] = anotherone[e]
144
+ recipients += 1
145
+ end
146
+
147
+ if recipients == 0
148
+ # Try to pick an recipient address from the original message
149
+ p1 = emailparts[1].index("\nTo: ") || -1
150
+ p2 = emailparts[1].index("\n", p1 + 6) || -1
151
+
152
+ if p1 > 0
153
+ # Get the recipient address from "To:" header at the original message
154
+ cv = Sisimai::Address.s3s4(emailparts[1][p1, p2 - p1 - 5])
155
+ return nil unless Sisimai::Address.is_emailaddress(cv)
156
+ dscontents[0]["recipient"] = cv
157
+ recipients += 1
158
+ end
159
+ end
125
160
  end
126
161
  return nil unless recipients > 0
127
162
 
128
- dscontents.each do |e|
129
- errorindex += 1
130
- e.delete('sessionerr')
131
-
132
- e['diagnosis'] ||= if anotherset['diagnosis'].to_s.size > 0
133
- # Copy alternative error message
134
- anotherset['diagnosis']
135
- else
136
- # Set server response as a error message
137
- responding[errorindex]
138
- end
139
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
140
- e['replycode'] = Sisimai::SMTP::Reply.find(e['diagnosis']) || anotherset['replycode']
141
- e['command'] = commandset[errorindex] || Sisimai::SMTP::Command.find(e['diagnosis']) || ''
163
+ j = 0; dscontents.each do |e|
164
+ # Tidy up the error message in e.Diagnosis
165
+ e["diagnosis"] = anotherone[j] if e["diagnosis"].empty?
166
+ e["diagnosis"] = Sisimai::String.sweep(e["diagnosis"])
167
+ e["command"] = Sisimai::SMTP::Command.find(e["diagnosis"]) if e["command"].empty?
168
+ e["replycode"] = Sisimai::SMTP::Reply.find(e["diagnosis"])
169
+ e["replycode"] = Sisimai::SMTP::Reply.find(anotherone[j]) if e["replycode"].empty?
142
170
 
143
171
  # @example.jp, no local part
144
172
  # Get email address from the value of Diagnostic-Code header
@@ -64,7 +64,7 @@ module Sisimai::Lhost
64
64
  # RCPT TO: *****@vtext.com
65
65
  v = dscontents[-1]
66
66
  if e.start_with?(' RCPT TO: ')
67
- if v['recipient']
67
+ if v["recipient"] != ""
68
68
  # There are multiple recipient addresses in the message body.
69
69
  dscontents << Sisimai::Lhost.DELIVERYSTATUS
70
70
  v = dscontents[-1]
@@ -112,7 +112,7 @@ module Sisimai::Lhost
112
112
  # Date: Wed, 20 Jun 2013 10:29:52 +0000
113
113
  v = dscontents[-1]
114
114
  if e.start_with?('To: ')
115
- if v['recipient']
115
+ if v["recipient"] != ""
116
116
  # There are multiple recipient addresses in the message body.
117
117
  dscontents << Sisimai::Lhost.DELIVERYSTATUS
118
118
  v = dscontents[-1]
@@ -47,7 +47,7 @@ module Sisimai::Lhost
47
47
 
48
48
  if Sisimai::String.aligned(e, ['@', ' [', ']'])
49
49
  # kijitora@example.co.jp [User unknown]
50
- if v['recipient']
50
+ if v["recipient"] != ""
51
51
  # There are multiple recipient addresses in the message body.
52
52
  dscontents << Sisimai::Lhost.DELIVERYSTATUS
53
53
  v = dscontents[-1]
@@ -49,7 +49,7 @@ module Sisimai::Lhost
49
49
 
50
50
  if e.start_with?('<') && Sisimai::String.aligned(e, ['<', '@', '>', ':'])
51
51
  # <kijitora@example.com>:
52
- if v['recipient']
52
+ if v["recipient"] != ""
53
53
  # There are multiple recipient addresses in the message body.
54
54
  dscontents << Sisimai::Lhost.DELIVERYSTATUS
55
55
  v = dscontents[-1]
@@ -58,7 +58,6 @@ module Sisimai::Lhost
58
58
  recipients += 1
59
59
  else
60
60
  # This user doesn't have a example.com account (kijitora@example.com) [0]
61
- v['diagnosis'] ||= ''
62
61
  v['diagnosis'] << ' ' << e
63
62
  end
64
63
  end
@@ -56,7 +56,7 @@ module Sisimai::Lhost
56
56
 
57
57
  if e.include?(' * ') && e.include?('@')
58
58
  # * kijitora@example.com
59
- if v['recipient']
59
+ if v["recipient"] != ""
60
60
  # There are multiple recipient addresses in the message body.
61
61
  dscontents << Sisimai::Lhost.DELIVERYSTATUS
62
62
  v = dscontents[-1]
@@ -84,7 +84,7 @@ module Sisimai::Lhost
84
84
 
85
85
  dscontents.each do |e|
86
86
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
87
- e['status'] = Sisimai::SMTP::Status.find(e['diagnosis']) || ''
87
+ e['status'] = Sisimai::SMTP::Status.find(e['diagnosis'])
88
88
  end
89
89
 
90
90
  return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
@@ -52,7 +52,7 @@ module Sisimai::Lhost
52
52
  if p1 == 0 || p2 == 0
53
53
  # SMTP Server <mta2.example.jp> rejected recipient <kijitora@examplejp>
54
54
  # The following recipients returned permanent errors: neko@example.jp.
55
- if v['recipient']
55
+ if v["recipient"] != ""
56
56
  # There are multiple recipient addresses in the message body.
57
57
  dscontents << Sisimai::Lhost.DELIVERYSTATUS
58
58
  v = dscontents[-1]
@@ -55,7 +55,7 @@ module Sisimai::Lhost
55
55
 
56
56
  if Sisimai::String.aligned(e, ['@', ' ', 'ERROR_CODE :'])
57
57
  # kijitora@example.co.jp Invalid Address, ERROR_CODE :550, ERROR_CODE :5.1.=
58
- if v['recipient']
58
+ if v["recipient"] != ""
59
59
  # There are multiple recipient addresses in the message body.
60
60
  dscontents << Sisimai::Lhost.DELIVERYSTATUS
61
61
  v = dscontents[-1]
@@ -73,7 +73,7 @@ module Sisimai::Lhost
73
73
  elsif e.start_with?('[Status: ')
74
74
  # Expired
75
75
  # [Status: Error, Address: <kijitora@6kaku.example.co.jp>, ResponseCode 421, , Host not reachable.]
76
- if v['recipient']
76
+ if v["recipient"] != ""
77
77
  # There are multiple recipient addresses in the message body.
78
78
  dscontents << Sisimai::Lhost.DELIVERYSTATUS
79
79
  v = dscontents[-1]
data/lib/sisimai/lhost.rb CHANGED
@@ -9,21 +9,20 @@ module Sisimai
9
9
  # @private
10
10
  def DELIVERYSTATUS
11
11
  return {
12
- 'spec' => nil, # Protocl specification
13
- 'date' => nil, # The value of Last-Attempt-Date header
14
- 'rhost' => nil, # The value of Remote-MTA header
15
- 'lhost' => nil, # The value of Received-From-MTA header
16
- 'alias' => nil, # The value of alias entry(RHS)
17
- 'agent' => nil, # MTA module name
18
- 'action' => nil, # The value of Action header
19
- 'status' => nil, # The value of Status header
20
- 'reason' => nil, # Temporary reason of bounce
21
- 'command' => nil, # SMTP command in the message body
22
- 'replycode' => nil, # SMTP Reply code
23
- 'diagnosis' => nil, # The value of Diagnostic-Code header
24
- 'recipient' => nil, # The value of Final-Recipient header
25
- 'hardbounce' => nil, # Hard bounce or not
26
- 'feedbacktype' => nil, # Feedback Type
12
+ 'spec' => "", # Protocl specification
13
+ 'date' => "", # The value of Last-Attempt-Date header
14
+ 'rhost' => "", # The value of Remote-MTA header
15
+ 'lhost' => "", # The value of Received-From-MTA header
16
+ 'alias' => "", # The value of alias entry(RHS)
17
+ 'agent' => "", # MTA module name
18
+ 'action' => "", # The value of Action header
19
+ 'status' => "", # The value of Status header
20
+ 'reason' => "", # Temporary reason of bounce
21
+ 'command' => "", # SMTP command in the message body
22
+ 'replycode' => "", # SMTP Reply code
23
+ 'diagnosis' => "", # The value of Diagnostic-Code header
24
+ 'recipient' => "", # The value of Final-Recipient header
25
+ 'feedbacktype' => "", # Feedback Type
27
26
  }
28
27
  end
29
28
 
@@ -41,12 +40,10 @@ module Sisimai
41
40
  # @return [Array] MTA list with order
42
41
  def index
43
42
  return %w[
44
- Activehunter Amavis AmazonSES AmazonWorkMail Aol ApacheJames Barracuda Bigfoot Biglobe
45
- Courier Domino DragonFly EZweb EinsUndEins Exchange2003 Exchange2007 Exim FML Facebook GMX
46
- GSuite GoogleGroups Gmail IMailServer InterScanMSS KDDI MXLogic MailFoundry MailMarshalSMTP
47
- MailRu McAfee MessageLabs MessagingServer Notes Office365 OpenSMTPD Outlook Postfix
48
- PowerMTA ReceivingSES SendGrid Sendmail SurfControl V5sendmail Verizon X1 X2 X3 X4 X5 X6
49
- Yahoo Yandex Zoho MFILTER Qmail
43
+ Activehunter AmazonSES ApacheJames Biglobe Courier Domino DragonFly EZweb EinsUndEins Exchange2003
44
+ Exchange2007 Exim FML GMX GoogleWorkspace GoogleGroups Gmail IMailServer InterScanMSS KDDI
45
+ MailFoundry MailMarshalSMTP MessagingServer Notes OpenSMTPD Postfix Sendmail V5sendmail
46
+ Verizon X1 X2 X3 X6 Zoho MFILTER Qmail
50
47
  ]
51
48
  end
52
49