sisimai 4.22.5 → 4.22.6

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 (140) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +20 -0
  3. data/README-JA.md +2 -2
  4. data/README.md +2 -2
  5. data/lib/sisimai/bite/email/amazonses.rb +3 -3
  6. data/lib/sisimai/bite/email/aol.rb +5 -5
  7. data/lib/sisimai/bite/email/biglobe.rb +5 -5
  8. data/lib/sisimai/bite/email/courier.rb +6 -17
  9. data/lib/sisimai/bite/email/domino.rb +10 -13
  10. data/lib/sisimai/bite/email/einsundeins.rb +3 -3
  11. data/lib/sisimai/bite/email/exim.rb +37 -42
  12. data/lib/sisimai/bite/email/gmx.rb +3 -3
  13. data/lib/sisimai/bite/email/google.rb +12 -14
  14. data/lib/sisimai/bite/email/gsuite.rb +7 -7
  15. data/lib/sisimai/bite/email/kddi.rb +6 -6
  16. data/lib/sisimai/bite/email/mailru.rb +31 -21
  17. data/lib/sisimai/bite/email/messagingserver.rb +3 -3
  18. data/lib/sisimai/bite/email/mxlogic.rb +55 -35
  19. data/lib/sisimai/bite/email/notes.rb +8 -9
  20. data/lib/sisimai/bite/email/office365.rb +13 -3
  21. data/lib/sisimai/bite/email/opensmtpd.rb +23 -21
  22. data/lib/sisimai/bite/email/outlook.rb +5 -5
  23. data/lib/sisimai/bite/email/qmail.rb +42 -51
  24. data/lib/sisimai/bite/email/receivingses.rb +7 -7
  25. data/lib/sisimai/bite/email/verizon.rb +6 -6
  26. data/lib/sisimai/bite/email/x4.rb +42 -51
  27. data/lib/sisimai/bite/email/yahoo.rb +5 -0
  28. data/lib/sisimai/bite/email/zoho.rb +3 -3
  29. data/lib/sisimai/data.rb +1 -0
  30. data/lib/sisimai/mda.rb +41 -45
  31. data/lib/sisimai/mime.rb +37 -12
  32. data/lib/sisimai/reason/filtered.rb +15 -22
  33. data/lib/sisimai/reason/notaccept.rb +2 -0
  34. data/lib/sisimai/reason/spamdetected.rb +1 -0
  35. data/lib/sisimai/rhost.rb +2 -1
  36. data/lib/sisimai/rhost/kddi.rb +40 -0
  37. data/lib/sisimai/smtp/error.rb +2 -12
  38. data/lib/sisimai/version.rb +1 -1
  39. data/set-of-emails/README.md +19 -9
  40. data/set-of-emails/logo/horizontalversions.png +0 -0
  41. data/set-of-emails/logo/icon.png +0 -0
  42. data/set-of-emails/maildir/bsd/arf-15.eml +57 -0
  43. data/set-of-emails/maildir/bsd/arf-16.eml +68 -0
  44. data/set-of-emails/maildir/bsd/{arf-05.eml → arf-17.eml} +29 -34
  45. data/set-of-emails/maildir/bsd/arf-18.eml +59 -0
  46. data/set-of-emails/maildir/bsd/arf-19.eml +67 -0
  47. data/set-of-emails/maildir/bsd/arf-20.eml +64 -0
  48. data/set-of-emails/maildir/bsd/arf-21.eml +57 -0
  49. data/set-of-emails/maildir/bsd/arf-22.eml +49 -0
  50. data/set-of-emails/maildir/bsd/{email-amazonworkmail-06.eml → email-amazonworkmail-08.eml} +4 -4
  51. data/set-of-emails/maildir/bsd/email-bigfoot-02.eml +66 -0
  52. data/set-of-emails/maildir/bsd/email-einsundeins-02.eml +45 -0
  53. data/set-of-emails/maildir/bsd/email-exchange2003-07.eml +63 -0
  54. data/set-of-emails/maildir/bsd/email-ezweb-07.eml +39 -0
  55. data/set-of-emails/maildir/bsd/{email-facebook-01.eml → email-facebook-03.eml} +7 -7
  56. data/set-of-emails/maildir/bsd/{email-facebook-02.eml → email-facebook-04.eml} +7 -7
  57. data/set-of-emails/maildir/bsd/email-fml-03.eml +69 -0
  58. data/set-of-emails/maildir/bsd/{email-google-02.eml → email-google-18.eml} +21 -20
  59. data/set-of-emails/maildir/bsd/email-gsuite-08.eml +231 -0
  60. data/set-of-emails/maildir/bsd/email-gsuite-09.eml +231 -0
  61. data/set-of-emails/maildir/bsd/email-gsuite-10.eml +254 -0
  62. data/set-of-emails/maildir/bsd/email-gsuite-11.eml +228 -0
  63. data/set-of-emails/maildir/bsd/email-mailmarshalsmtp-02.eml +43 -0
  64. data/set-of-emails/maildir/bsd/email-mailru-07.eml +82 -0
  65. data/set-of-emails/maildir/bsd/email-mailru-08.eml +82 -0
  66. data/set-of-emails/maildir/bsd/email-mailru-09.eml +80 -0
  67. data/set-of-emails/maildir/bsd/email-messagelabs-02.eml +72 -0
  68. data/set-of-emails/maildir/bsd/email-messagingserver-08.eml +150 -0
  69. data/set-of-emails/maildir/bsd/email-messagingserver-09.eml +153 -0
  70. data/set-of-emails/maildir/bsd/email-messagingserver-10.eml +145 -0
  71. data/set-of-emails/maildir/bsd/email-messagingserver-11.eml +151 -0
  72. data/set-of-emails/maildir/bsd/email-office365-04.eml +635 -0
  73. data/set-of-emails/maildir/bsd/email-office365-05.eml +561 -0
  74. data/set-of-emails/maildir/bsd/email-outlook-08.eml +69 -0
  75. data/set-of-emails/maildir/bsd/email-postfix-33.eml +71 -0
  76. data/set-of-emails/maildir/bsd/email-postfix-34.eml +54 -0
  77. data/set-of-emails/maildir/bsd/email-postfix-35.eml +70 -0
  78. data/set-of-emails/maildir/bsd/email-postfix-36.eml +73 -0
  79. data/set-of-emails/maildir/bsd/email-sendmail-49.eml +67 -0
  80. data/set-of-emails/maildir/bsd/email-sendmail-50.eml +67 -0
  81. data/set-of-emails/maildir/bsd/email-sendmail-51.eml +75 -0
  82. data/set-of-emails/maildir/bsd/email-sendmail-52.eml +68 -0
  83. data/set-of-emails/maildir/bsd/email-x3-05.eml +67 -0
  84. data/set-of-emails/maildir/bsd/email-x4-08.eml +36 -0
  85. data/set-of-emails/maildir/bsd/email-yahoo-06.eml +76 -0
  86. data/set-of-emails/maildir/bsd/email-yahoo-07.eml +76 -0
  87. data/set-of-emails/maildir/bsd/email-yahoo-08.eml +75 -0
  88. data/set-of-emails/maildir/bsd/email-yahoo-09.eml +76 -0
  89. data/set-of-emails/maildir/bsd/email-yahoo-10.eml +75 -0
  90. data/set-of-emails/maildir/bsd/email-yahoo-11.eml +80 -0
  91. data/set-of-emails/maildir/bsd/rfc3464-35.eml +43 -0
  92. data/set-of-emails/maildir/bsd/rfc3464-36.eml +40 -0
  93. data/set-of-emails/maildir/bsd/rfc3464-37.eml +50 -0
  94. data/set-of-emails/maildir/bsd/rfc3464-38.eml +17 -0
  95. data/set-of-emails/maildir/bsd/rfc3464-39.eml +23 -0
  96. data/set-of-emails/maildir/bsd/rfc3464-40.eml +115 -0
  97. data/set-of-emails/maildir/bsd/rhost-godaddy-03.eml +81 -0
  98. data/set-of-emails/maildir/bsd/rhost-kddi-01.eml +67 -0
  99. data/set-of-emails/maildir/bsd/rhost-kddi-02.eml +68 -0
  100. data/set-of-emails/maildir/dos/email-gsuite-01.eml +189 -0
  101. data/set-of-emails/maildir/dos/rfc3834-01.eml +22 -36
  102. data/set-of-emails/maildir/dos/rhost-franceptt-01.eml +102 -0
  103. data/set-of-emails/maildir/mac/email-gsuite-01.eml +1 -10
  104. data/set-of-emails/maildir/mac/rfc3834-01.eml +1 -1
  105. data/set-of-emails/maildir/mac/rhost-franceptt-01.eml +1 -4
  106. metadata +67 -41
  107. data/set-of-emails/maildir/bsd/arf-03.eml +0 -56
  108. data/set-of-emails/maildir/bsd/arf-04.eml +0 -89
  109. data/set-of-emails/maildir/bsd/arf-06.eml +0 -166
  110. data/set-of-emails/maildir/bsd/arf-07.eml +0 -59
  111. data/set-of-emails/maildir/bsd/arf-08.eml +0 -103
  112. data/set-of-emails/maildir/bsd/arf-09.eml +0 -104
  113. data/set-of-emails/maildir/bsd/arf-10.eml +0 -56
  114. data/set-of-emails/maildir/bsd/arf-13.eml +0 -76
  115. data/set-of-emails/maildir/bsd/email-amazonses-04.eml +0 -55
  116. data/set-of-emails/maildir/bsd/email-bigfoot-01.eml +0 -64
  117. data/set-of-emails/maildir/bsd/email-einsundeins-01.eml +0 -38
  118. data/set-of-emails/maildir/bsd/email-exchange2003-06.eml +0 -151
  119. data/set-of-emails/maildir/bsd/email-ezweb-06.eml +0 -33
  120. data/set-of-emails/maildir/bsd/email-fml-01.eml +0 -70
  121. data/set-of-emails/maildir/bsd/email-google-14.eml +0 -304
  122. data/set-of-emails/maildir/bsd/email-mailmarshalsmtp-01.eml +0 -43
  123. data/set-of-emails/maildir/bsd/email-messagelabs-01.eml +0 -76
  124. data/set-of-emails/maildir/bsd/email-outlook-05.eml +0 -85
  125. data/set-of-emails/maildir/bsd/email-postfix-12.eml +0 -71
  126. data/set-of-emails/maildir/bsd/email-postfix-21.eml +0 -60
  127. data/set-of-emails/maildir/bsd/email-x3-04.eml +0 -106
  128. data/set-of-emails/maildir/bsd/email-x4-07.eml +0 -153
  129. data/set-of-emails/maildir/bsd/rfc3464-02.eml +0 -43
  130. data/set-of-emails/maildir/bsd/rfc3464-03.eml +0 -40
  131. data/set-of-emails/maildir/bsd/rfc3464-22.eml +0 -105
  132. data/set-of-emails/maildir/bsd/rfc3464-23.eml +0 -21
  133. data/set-of-emails/maildir/bsd/rfc3464-25.eml +0 -33
  134. data/set-of-emails/maildir/bsd/rfc3464-27.eml +0 -180
  135. data/set-of-emails/maildir/bsd/rhost-godaddy-01.eml +0 -83
  136. data/set-of-emails/to-be-debugged-because/reason-is-onhold/onhold-0001.eml +0 -85
  137. data/set-of-emails/to-be-debugged-because/reason-is-undefined/undefined-0002.eml +0 -27
  138. data/set-of-emails/to-be-debugged-because/reason-is-undefined/undefined-0003.eml +0 -78
  139. data/set-of-emails/to-be-debugged-because/sisimai-cannot-parse-yet/cannot-parse-this-email-0002.eml +0 -25
  140. data/set-of-emails/to-be-debugged-because/something-is-wrong/no-message-id-from-pr-150.eml +0 -75
@@ -13,12 +13,12 @@ module Sisimai::Bite::Email
13
13
  message: ['This message could not be delivered.'],
14
14
  rfc822: ['content-type: text/rfc822-headers'],
15
15
  }.freeze
16
- ReFailures = {
16
+ MessagesOf = {
17
17
  # The followings are error messages in Rule sets/*/Actions/Template
18
- filtered: %r/Mailbox does not exist/,
19
- mesgtoobig: %r/Message too large/,
20
- mailboxfull: %r/Mailbox full/,
21
- contenterror: %r/Message content rejected/,
18
+ filtered: ['Mailbox does not exist'],
19
+ mesgtoobig: ['Message too large'],
20
+ mailboxfull: ['Mailbox full'],
21
+ contenterror: ['Message content rejected'],
22
22
  }.freeze
23
23
 
24
24
  def description; return 'Amazon SES(Receiving): http://aws.amazon.com/ses/'; end
@@ -192,9 +192,9 @@ module Sisimai::Bite::Email
192
192
  e['status'] = pseudostatus if pseudostatus.size > 0
193
193
  end
194
194
 
195
- ReFailures.each_key do |r|
195
+ MessagesOf.each_key do |r|
196
196
  # Verify each regular expression of session errors
197
- next unless e['diagnosis'] =~ ReFailures[r]
197
+ next unless MessagesOf[r].find { |a| e['diagnosis'].include?(a) }
198
198
  e['reason'] = r.to_s
199
199
  break
200
200
  end
@@ -51,7 +51,7 @@ module Sisimai::Bite::Email
51
51
 
52
52
  markingsof = {} # (Hash) Delimiter patterns
53
53
  startingof = {} # (Hash) Delimiter strings
54
- reFailures = {} # (Hash) Error message patterns
54
+ messagesof = {} # (Hash) Error message patterns
55
55
  boundary00 = '' # (String) Boundary string
56
56
  v = nil
57
57
 
@@ -61,9 +61,9 @@ module Sisimai::Bite::Email
61
61
  message: %r/\AError:[ \t]/,
62
62
  rfc822: %r/\A__BOUNDARY_STRING_HERE__\z/,
63
63
  }
64
- reFailures = {
64
+ messagesof = {
65
65
  # The attempted recipient address does not exist.
66
- userunknown: %r/550 [-] Requested action not taken: no such user here/,
66
+ userunknown: ['550 - Requested action not taken: no such user here'],
67
67
  }
68
68
  boundary00 = Sisimai::MIME.boundary(mhead['content-type']) || ''
69
69
 
@@ -137,7 +137,7 @@ module Sisimai::Bite::Email
137
137
  # vzwpix.com
138
138
  startingof = { message: ['Message could not be delivered to mobile'] }
139
139
  markingsof = { rfc822: %r/\A__BOUNDARY_STRING_HERE__\z/ }
140
- reFailures = { userunknown: %r/No valid recipients for this MM/ }
140
+ messagesof = { userunknown: ['No valid recipients for this MM'] }
141
141
  boundary00 = Sisimai::MIME.boundary(mhead['content-type'])
142
142
 
143
143
  if boundary00.size > 0
@@ -222,9 +222,9 @@ module Sisimai::Bite::Email
222
222
  e['agent'] = self.smtpagent
223
223
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
224
224
 
225
- reFailures.each_key do |r|
225
+ messagesof.each_key do |r|
226
226
  # Verify each regular expression of session errors
227
- next unless e['diagnosis'] =~ reFailures[r]
227
+ next unless messagesof[r].find { |a| e['diagnosis'].include?(a) }
228
228
  e['reason'] = r.to_s
229
229
  break
230
230
  end
@@ -70,62 +70,53 @@ module Sisimai::Bite::Email
70
70
  |remote[ ]host[ ]([-0-9a-zA-Z.]+[0-9a-zA-Z])[ ]said:
71
71
  )
72
72
  }x
73
- # qmail-ldap-1.03-20040101.patch:19817 - 19866
74
- ReLDAP = {
75
- suspend: %r/Mailaddress is administrative?le?y disabled/, # 5.2.1
76
- userunknown: %r/[Ss]orry, no mailbox here by that name/, # 5.1.1
77
- exceedlimit: %r/The message exeeded the maximum size the user accepts/, # 5.2.3
78
- systemerror: %r{(?>
79
- Automatic[ ]homedir[ ]creator[ ]crashed # 4.3.0
80
- |Illegal[ ]value[ ]in[ ]LDAP[ ]attribute # 5.3.5
81
- |LDAP[ ]attribute[ ]is[ ]not[ ]given[ ]but[ ]mandatory # 5.3.5
82
- |Timeout[ ]while[ ]performing[ ]search[ ]on[ ]LDAP[ ]server # 4.4.3
83
- |Too[ ]many[ ]results[ ]returned[ ]but[ ]needs[ ]to[ ]be[ ]unique # 5.3.5
84
- |Permanent[ ]error[ ]while[ ]executing[ ]qmail[-]forward # 5.4.4
85
- |Temporary[ ](?:
86
- error[ ](?:
87
- in[ ]automatic[ ]homedir[ ]creation # 4.3.0 or 5.3.0
88
- |while[ ]executing[ ]qmail[-]forward # 4.4.4
89
- )
90
- |failure[ ]in[ ]LDAP[ ]lookup # 4.4.3
91
- )
92
- |Unable[ ]to[ ](?:
93
- contact[ ]LDAP[ ]server # 4.4.3
94
- |login[ ]into[ ]LDAP[ ]server,[ ]bad[ ]credentials # 4.4.3
95
- )
96
- )
97
- }x,
98
- }.freeze
99
73
 
100
74
  # qmail-send.c:922| ... (&dline[c],"I'm not going to try again; this message has been in the queue too long.\n")) nomem();
101
- ReDelaying = %r/this message has been in the queue too long[.]\z/
75
+ HasExpired = 'this message has been in the queue too long.'
102
76
  ReIsOnHold = %r/\A[^ ]+ does not like recipient[.][ ]+.+this message has been in the queue too long[.]\z/
103
77
  ReCommands = %r/Sorry, no SMTP connection got far enough; most progress was ([A-Z]{4})[ ]/
104
- ReFailures = {
78
+ FailOnLDAP = {
79
+ # qmail-ldap-1.03-20040101.patch:19817 - 19866
80
+ suspend: ['Mailaddress is administrative?le?y disabled'], # 5.2.1
81
+ userunknown: ['Sorry, no mailbox here by that name'], # 5.1.1
82
+ exceedlimit: ['The message exeeded the maximum size the user accepts'], # 5.2.3
83
+ systemerror: [
84
+ 'Automatic homedir creator crashed', # 4.3.0
85
+ 'Illegal value in LDAP attribute', # 5.3.5
86
+ 'LDAP attribute is not given but mandatory', # 5.3.5
87
+ 'Timeout while performing search on LDAP server', # 4.4.3
88
+ 'Too many results returned but needs to be unique', # 5.3.5
89
+ 'Permanent error while executing qmail-forward', # 5.4.4
90
+ 'Temporary error in automatic homedir creation', # 4.3.0 or 5.3.0
91
+ 'Temporary error while executing qmail-forward', # 4.4.4
92
+ 'Temporary failure in LDAP lookup', # 4.4.3
93
+ 'Unable to contact LDAP server', # 4.4.3
94
+ 'Unable to login into LDAP server, bad credentials',# 4.4.3
95
+ ],
96
+ }.freeze
97
+ MessagesOf = {
105
98
  # qmail-local.c:589| strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)");
106
99
  # qmail-remote.c:253| out("s"); outhost(); out(" does not like recipient.\n");
107
- userunknown: %r/(?:no mailbox here by that name | does not like recipient[.])/,
100
+ userunknown: ['no mailbox here by that name', 'does not like recipient.'],
108
101
  # error_str.c:192| X(EDQUOT,"disk quota exceeded")
109
- mailboxfull: %r/disk quota exceeded/,
102
+ mailboxfull: ['disk quota exceeded'],
110
103
  # qmail-qmtpd.c:233| ... result = "Dsorry, that message size exceeds my databytes limit (#5.3.4)";
111
104
  # qmail-smtpd.c:391| ... out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return;
112
- mesgtoobig: %r/Message size exceeds fixed maximum message size:/,
105
+ mesgtoobig: ['Message size exceeds fixed maximum message size:'],
113
106
  # qmail-remote.c:68| Sorry, I couldn't find any host by that name. (#4.1.2)\n"); zerodie();
114
107
  # qmail-remote.c:78| Sorry, I couldn't find any host named ");
115
- hostunknown: %r/\ASorry, I couldn't find any host /,
116
- systemfull: %r/Requested action not taken: mailbox unavailable [(]not enough free space[)]/,
117
- systemerror: %r{(?>
118
- bad[ ]interpreter:[ ]No[ ]such[ ]file[ ]or[ ]directory
119
- |system[ ]error
120
- |Unable[ ]to\b
121
- )
122
- }x,
123
- networkerror: %r{Sorry(?:
124
- [,][ ]I[ ]wasn[']t[ ]able[ ]to[ ]establish[ ]an[ ]SMTP[ ]connection
125
- |[,][ ]I[ ]couldn[']t[ ]find[ ]a[ ]mail[ ]exchanger[ ]or[ ]IP[ ]address
126
- |[.][ ]Although[ ]I[']m[ ]listed[ ]as[ ]a[ ]best[-]preference[ ]MX[ ]or[ ]A[ ]for[ ]that[ ]host
127
- )
128
- }x,
108
+ hostunknown: ["Sorry, I couldn't find any host "],
109
+ systemfull: ['Requested action not taken: mailbox unavailable (not enough free space)'],
110
+ systemerror: [
111
+ 'bad interpreter: No such file or directory',
112
+ 'system error',
113
+ 'Unable to',
114
+ ],
115
+ networkerror: [
116
+ "Sorry, I wasn't able to establish an SMTP connection",
117
+ "Sorry, I couldn't find a mail exchanger or IP address",
118
+ "Sorry. Although I'm listed as a best-preference MX or A for that host",
119
+ ],
129
120
  }.freeze
130
121
 
131
122
  def description; return 'Unknown MTA #4'; end
@@ -265,31 +256,31 @@ module Sisimai::Bite::Email
265
256
  # Sisimai::Reason::* modules
266
257
  e['reason'] = 'onhold'
267
258
  else
268
- ReFailures.each_key do |r|
259
+ MessagesOf.each_key do |r|
269
260
  # Verify each regular expression of session errors
270
261
  if e['alterrors']
271
262
  # Check the value of "alterrors"
272
- next unless e['alterrors'] =~ ReFailures[r]
263
+ next unless MessagesOf[r].find { |a| e['alterrors'].include?(a) }
273
264
  e['reason'] = r.to_s
274
265
  end
275
266
  break if e['reason']
276
267
 
277
- next unless e['diagnosis'] =~ ReFailures[r]
268
+ next unless MessagesOf[r].find { |a| e['diagnosis'].include?(a) }
278
269
  e['reason'] = r.to_s
279
270
  break
280
271
  end
281
272
 
282
273
  unless e['reason']
283
- ReLDAP.each_key do |r|
274
+ FailOnLDAP.each_key do |r|
284
275
  # Verify each regular expression of LDAP errors
285
- next unless e['diagnosis'] =~ ReLDAP[r]
276
+ next unless FailOnLDAP[r].find { |a| e['diagnosis'].include?(a) }
286
277
  e['reason'] = r.to_s
287
278
  break
288
279
  end
289
280
  end
290
281
 
291
282
  unless e['reason']
292
- e['reason'] = 'expired' if e['diagnosis'] =~ ReDelaying
283
+ e['reason'] = 'expired' if e['diagnosis'].include?(HasExpired)
293
284
  end
294
285
  end
295
286
  end
@@ -91,6 +91,7 @@ module Sisimai::Bite::Email
91
91
  v = dscontents[-1]
92
92
  end
93
93
  v['recipient'] = cv[1]
94
+ v['diagnosis'] = ''
94
95
  recipients += 1
95
96
  else
96
97
  if e.start_with?('Remote host said:')
@@ -116,6 +117,9 @@ module Sisimai::Bite::Email
116
117
  # 550 5.2.2 <mailboxfull@example.jp>... Mailbox Full
117
118
  v['diagnosis'] = e
118
119
  end
120
+ else
121
+ # Error message which does not start with 'Remote host said:'
122
+ v['diagnosis'] << ' ' << e
119
123
  end
120
124
  end
121
125
  end
@@ -128,6 +132,7 @@ module Sisimai::Bite::Email
128
132
  e['diagnosis'] = e['diagnosis'].gsub(/\\n/, ' ')
129
133
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
130
134
  e['agent'] = self.smtpagent
135
+ e['command'] ||= 'RCPT' if e['diagnosis'] =~ /[<].+[@].+[>]/
131
136
  end
132
137
 
133
138
  rfc822part = Sisimai::RFC5322.weedout(rfc822list)
@@ -11,7 +11,7 @@ module Sisimai::Bite::Email
11
11
  message: ['This message was created automatically by mail delivery'],
12
12
  rfc822: ['from mail.zoho.com by mx.zohomail.com'],
13
13
  }.freeze
14
- ReFailures = { expired: %r/Host not reachable/ }.freeze
14
+ MessagesOf = { expired: ['Host not reachable'] }.freeze
15
15
 
16
16
  def description; return 'Zoho Mail: https://www.zoho.com'; end
17
17
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
@@ -140,9 +140,9 @@ module Sisimai::Bite::Email
140
140
  e['diagnosis'] = e['diagnosis'].gsub(/\\n/, ' ')
141
141
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
142
142
 
143
- ReFailures.each_key do |r|
143
+ MessagesOf.each_key do |r|
144
144
  # Verify each regular expression of session errors
145
- next unless e['diagnosis'] =~ ReFailures[r]
145
+ next unless MessagesOf[r].find { |a| e['diagnosis'].include?(a) }
146
146
  e['reason'] = r.to_s
147
147
  break
148
148
  end
@@ -237,6 +237,7 @@ module Sisimai
237
237
 
238
238
  # Check space character in each value and get the first element
239
239
  p[v] = p[v].split(' ', 2).shift if p[v].include?(' ')
240
+ p[v] = p[v].chomp('.') # Remove "." at the end of the value
240
241
  end
241
242
 
242
243
  # Subject: header of the original message
@@ -23,59 +23,54 @@ module Sisimai
23
23
  }.freeze
24
24
 
25
25
  # dovecot/src/deliver/mail-send.c:94
26
- ReFailures = {
26
+ MessagesOf = {
27
27
  :'dovecot' => {
28
- :userunknown => %r/\Amailbox doesn't exist: /,
29
- :mailboxfull => %r{\A(?:
30
- quota[ ]exceeded # Dovecot 1.2 dovecot/src/plugins/quota/quota.c
31
- |quota[ ]exceeded[ ][(]mailbox[ ]for[ ]user[ ]is[ ]full[)] # dovecot/src/plugins/quota/quota.c
32
- |not[ ]enough[ ]disk[ ]space
33
- )
34
- }x,
28
+ userunknown: ["mailbox doesn't exist: "],
29
+ mailboxfull: [
30
+ 'quota exceeded', # Dovecot 1.2 dovecot/src/plugins/quota/quota.c
31
+ 'quota exceeded (mailbox for user is full)', # dovecot/src/plugins/quota/quota.c
32
+ 'not enough disk space',
33
+ ],
35
34
  },
36
35
  :'mail.local' => {
37
- :userunknown => %r{[:][ ](?:
38
- unknown[ ]user[:]
39
- |user[ ]unknown
40
- |invalid[ ]mailbox[ ]path
41
- |user[ ]missing[ ]home[ ]directory
42
- )
43
- }x,
44
- :mailboxfull => %r{(?:
45
- disc[ ]quota[ ]exceeded
46
- |mailbox[ ]full[ ]or[ ]quota[ ]exceeded
47
- )
48
- }x,
49
- :systemerror => %r/temporary file write error/,
36
+ userunknown: [
37
+ ': unknown user:',
38
+ ': user unknown',
39
+ ': invalid mailbox path',
40
+ ': user missing home directory',
41
+ ],
42
+ mailboxfull: [
43
+ 'disc quota exceeded',
44
+ 'mailbox full or quota exceeded',
45
+ ],
46
+ systemerror: ['temporary file write error'],
50
47
  },
51
48
  :'procmail' => {
52
- :mailboxfull => %r/quota exceeded while writing/,
53
- :systemfull => %r/no space left to finish writing/,
49
+ :mailboxfull => ['quota exceeded while writing'],
50
+ :systemfull => ['no space left to finish writing'],
54
51
  },
55
52
  :'maildrop' => {
56
- :userunknown => %r{(?:
57
- invalid[ ]user[ ]specified[.]
58
- |Cannot[ ]find[ ]system[ ]user
59
- )
60
- }x,
61
- :mailboxfull => %r/maildir over quota[.]\z/,
53
+ :userunknown => [
54
+ 'invalid user specified.',
55
+ 'Cannot find system user',
56
+ ],
57
+ :mailboxfull => ['maildir over quota.'],
62
58
  },
63
59
  :'vpopmail' => {
64
- :userunknown => %r/sorry, no mailbox here by that name[.]/,
65
- :filtered => %r{(?:
66
- account[ ]is[ ]locked[ ]email[ ]bounced
67
- |user[ ]does[ ]not[ ]exist,[ ]but[ ]will[ ]deliver[ ]to[ ]
68
- )
69
- }x,
70
- :mailboxfull => %r/(?:domain|user) is over quota/,
60
+ :userunknown => ['sorry, no mailbox here by that name.'],
61
+ :filtered => [
62
+ 'account is locked email bounced',
63
+ 'user does not exist, but will deliver to '
64
+ ],
65
+ :mailboxfull => ['domain is over quota', 'user is over quota'],
71
66
  },
72
67
  :'vmailmgr' => {
73
- :userunknown => %r{(?>
74
- invalid[ ]or[ ]unknown[ ](?:base[ ]user[ ]or[ ]domain|virtual[ ]user)
75
- |user[ ]name[ ]does[ ]not[ ]refer[ ]to[ ]a[ ]virtual[ ]user/
76
- )
77
- }x,
78
- :mailboxfull => %r/delivery failed due to system quota violation/,
68
+ :userunknown => [
69
+ 'invalid or unknown base user or domain',
70
+ 'invalid or unknown virtual user',
71
+ 'user name does not refer to a virtual user'
72
+ ],
73
+ mailboxfull: ['delivery failed due to system quota violation'],
79
74
  },
80
75
  }.freeze
81
76
 
@@ -125,11 +120,12 @@ module Sisimai
125
120
  return nil unless agentname0.size > 0
126
121
  return nil unless linebuffer.size > 0
127
122
 
128
- ReFailures[agentname0.to_sym].each_key do |e|
123
+ MessagesOf[agentname0.to_sym].each_key do |e|
129
124
  # Detect an error reason from message patterns of the MDA.
130
125
  linebuffer.each do |f|
131
- # Try to match with each regular expression
132
- next unless f.downcase =~ ReFailures[agentname0.to_sym][e]
126
+ # Whether the error message include each message defined in $MessagesOf
127
+ g = f.downcase
128
+ next unless MessagesOf[agentname0.to_sym][e].find { |a| g.include?(a) }
133
129
  reasonname = e.to_s
134
130
  bouncemesg = f
135
131
  break
@@ -131,10 +131,6 @@ module Sisimai
131
131
  return argv1.unpack('M').first unless argv1.downcase =~ ReE[:'quoted-print']
132
132
 
133
133
  boundary01 = Sisimai::MIME.boundary(heads['content-type'], 1)
134
- reboundary = {
135
- :begin => Regexp.new('\A' << Regexp.escape(boundary00)),
136
- :until => Regexp.new(Regexp.escape(boundary01) << '\z')
137
- }
138
134
  bodystring = ''
139
135
  notdecoded = ''
140
136
  getencoded = ''
@@ -143,6 +139,7 @@ module Sisimai
143
139
  encodename = nil
144
140
  ctencoding = nil
145
141
  mimeinside = false
142
+ mustencode = false
146
143
  hasdivided = argv1.split("\n")
147
144
 
148
145
  while e = hasdivided.shift do
@@ -153,11 +150,10 @@ module Sisimai
153
150
  # Content-Transfer-Encoding: quoted-printable
154
151
  if mimeinside
155
152
  # Quoted-Printable encoded text block
156
- if e =~ reboundary[:begin]
153
+ if e == boundary00
157
154
  # The next boundary string has appeared
158
155
  # --=_gy7C4Gpes0RP4V5Bs9cK4o2Us2ZT57b-3OLnRN+4klS8dTmQ
159
156
  getencoded = Sisimai::String.to_utf8(notdecoded.unpack('M').first, encodename)
160
-
161
157
  bodystring << getencoded
162
158
  bodystring << e + "\n"
163
159
 
@@ -166,7 +162,39 @@ module Sisimai
166
162
  ctencoding = false
167
163
  encodename = nil
168
164
  else
169
- # Inside of Queoted printable encoded text
165
+ # Inside of Quoted-Printable encoded text
166
+ if e.size > 76
167
+ # Invalid line exists in "quoted-printable" part
168
+ e = [e].pack('M').chomp
169
+ else
170
+ # A bounce message generated by Office365(Outlook) include lines
171
+ # which are not proper as Quoted-Printable:
172
+ # - `=` is not encoded
173
+ # - Longer than 76 charaters a line
174
+ #
175
+ # Content-Transfer-Encoding: quoted-printable
176
+ # X-Microsoft-Exchange-Diagnostics:
177
+ # 1;SLXP216MB0381;27:IdH7U/WHGgJu6J8lFrE7KvVxhnAwyKrNbSXMFYs3/Gzz6ZdXYYjzHj55K2O+cndpeVwkvBJqmo6y0IF4AhLfHtFzznw/BzhERU6wi/TCWRpyjYuW8v0/aTcflH3oAdgZ4Pwrp7PxLiiA8rYgU/E7SQ==
178
+ # ...
179
+ mustencode = true
180
+ while true do
181
+ break if e.end_with?(' ', "\t")
182
+ break if e.split('').find { |c| c.ord < 32 || c.ord > 126 }
183
+ if e.end_with?('=')
184
+ # Padding character of Base64 or not
185
+ break if e =~ /[\+\/0-9A-Za-z]{32,}[=]+\z/
186
+ else
187
+ if e.include?('=') && ! e.upcase.include?('=3D')
188
+ # Including "=" not as "=3D"
189
+ break
190
+ end
191
+ end
192
+ mustencode = false
193
+ break
194
+ end
195
+ e = [e].pack('M').chomp if mustencode
196
+ mustencode = false
197
+ end
170
198
  notdecoded << e + "\n"
171
199
  end
172
200
  else
@@ -179,10 +207,6 @@ module Sisimai
179
207
  # New boundary string has appeared
180
208
  boundary00 = e
181
209
  boundary01 = e + '--'
182
- reboundary = {
183
- :begin => Regexp.new('\A' << Regexp.escape(boundary00)),
184
- :until => Regexp.new(Regexp.escape(boundary01) << '\z')
185
- }
186
210
  end
187
211
  elsif cv = lowercased.match(ReE[:'with-charset']) || lowercased.match(ReE[:'only-charset'])
188
212
  # Content-Type: text/plain; charset=ISO-2022-JP
@@ -194,7 +218,7 @@ module Sisimai
194
218
  ctencoding = true
195
219
  mimeinside = true if encodename
196
220
 
197
- elsif e =~ reboundary[:until]
221
+ elsif e == boundary01
198
222
  # The end of boundary block
199
223
  # --=_gy7C4Gpes0RP4V5Bs9cK4o2Us2ZT57b-3OLnRN+4klS8dTmQ--
200
224
  mimeinside = false
@@ -204,6 +228,7 @@ module Sisimai
204
228
  end
205
229
  end
206
230
 
231
+ bodystring << notdecoded unless notdecoded.empty?
207
232
  return bodystring
208
233
  end
209
234