sisimai 4.22.3-java → 4.22.4-java
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sisimai might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/Benchmarks.mk +54 -0
- data/ChangeLog.md +23 -2
- data/Developers.mk +42 -35
- data/Makefile +10 -0
- data/README-JA.md +13 -13
- data/README.md +14 -14
- data/lib/sisimai.rb +12 -18
- data/lib/sisimai/address.rb +64 -82
- data/lib/sisimai/arf.rb +27 -42
- data/lib/sisimai/bite/email.rb +2 -4
- data/lib/sisimai/bite/email/activehunter.rb +12 -17
- data/lib/sisimai/bite/email/amazonses.rb +30 -48
- data/lib/sisimai/bite/email/amazonworkmail.rb +20 -27
- data/lib/sisimai/bite/email/aol.rb +27 -35
- data/lib/sisimai/bite/email/apachejames.rb +17 -28
- data/lib/sisimai/bite/email/bigfoot.rb +20 -33
- data/lib/sisimai/bite/email/biglobe.rb +15 -24
- data/lib/sisimai/bite/email/courier.rb +37 -61
- data/lib/sisimai/bite/email/domino.rb +19 -28
- data/lib/sisimai/bite/email/einsundeins.rb +20 -34
- data/lib/sisimai/bite/email/exchange2003.rb +25 -43
- data/lib/sisimai/bite/email/exchange2007.rb +15 -23
- data/lib/sisimai/bite/email/exim.rb +101 -120
- data/lib/sisimai/bite/email/ezweb.rb +28 -44
- data/lib/sisimai/bite/email/facebook.rb +26 -37
- data/lib/sisimai/bite/email/fml.rb +11 -20
- data/lib/sisimai/bite/email/gmx.rb +17 -27
- data/lib/sisimai/bite/email/google.rb +19 -29
- data/lib/sisimai/bite/email/gsuite.rb +39 -48
- data/lib/sisimai/bite/email/imailserver.rb +25 -39
- data/lib/sisimai/bite/email/interscanmss.rb +19 -26
- data/lib/sisimai/bite/email/kddi.rb +20 -33
- data/lib/sisimai/bite/email/mailfoundry.rb +14 -24
- data/lib/sisimai/bite/email/mailmarshalsmtp.rb +15 -24
- data/lib/sisimai/bite/email/mailru.rb +40 -59
- data/lib/sisimai/bite/email/mcafee.rb +21 -35
- data/lib/sisimai/bite/email/messagelabs.rb +23 -38
- data/lib/sisimai/bite/email/messagingserver.rb +15 -27
- data/lib/sisimai/bite/email/mfilter.rb +19 -28
- data/lib/sisimai/bite/email/mxlogic.rb +31 -49
- data/lib/sisimai/bite/email/notes.rb +16 -24
- data/lib/sisimai/bite/email/office365.rb +29 -38
- data/lib/sisimai/bite/email/opensmtpd.rb +50 -67
- data/lib/sisimai/bite/email/outlook.rb +24 -36
- data/lib/sisimai/bite/email/postfix.rb +33 -42
- data/lib/sisimai/bite/email/qmail.rb +44 -59
- data/lib/sisimai/bite/email/receivingses.rb +28 -36
- data/lib/sisimai/bite/email/sendgrid.rb +28 -37
- data/lib/sisimai/bite/email/sendmail.rb +35 -51
- data/lib/sisimai/bite/email/surfcontrol.rb +17 -25
- data/lib/sisimai/bite/email/userdefined.rb +17 -28
- data/lib/sisimai/bite/email/v5sendmail.rb +32 -41
- data/lib/sisimai/bite/email/verizon.rb +31 -56
- data/lib/sisimai/bite/email/x1.rb +11 -18
- data/lib/sisimai/bite/email/x2.rb +11 -23
- data/lib/sisimai/bite/email/x3.rb +10 -19
- data/lib/sisimai/bite/email/x4.rb +46 -65
- data/lib/sisimai/bite/email/x5.rb +26 -37
- data/lib/sisimai/bite/email/yahoo.rb +11 -19
- data/lib/sisimai/bite/email/yandex.rb +19 -30
- data/lib/sisimai/bite/email/zoho.rb +21 -30
- data/lib/sisimai/bite/json.rb +1 -2
- data/lib/sisimai/bite/json/amazonses.rb +20 -25
- data/lib/sisimai/bite/json/sendgrid.rb +1 -1
- data/lib/sisimai/data.rb +36 -55
- data/lib/sisimai/data/json.rb +3 -3
- data/lib/sisimai/data/yaml.rb +1 -1
- data/lib/sisimai/datetime.rb +5 -21
- data/lib/sisimai/mail.rb +4 -6
- data/lib/sisimai/mail/maildir.rb +1 -1
- data/lib/sisimai/mda.rb +41 -44
- data/lib/sisimai/message.rb +2 -3
- data/lib/sisimai/message/email.rb +42 -52
- data/lib/sisimai/message/json.rb +7 -7
- data/lib/sisimai/mime.rb +25 -23
- data/lib/sisimai/order/email.rb +2 -2
- data/lib/sisimai/order/json.rb +2 -7
- data/lib/sisimai/reason.rb +41 -46
- data/lib/sisimai/reason/blocked.rb +60 -71
- data/lib/sisimai/reason/contenterror.rb +4 -8
- data/lib/sisimai/reason/delivered.rb +1 -3
- data/lib/sisimai/reason/exceedlimit.rb +10 -20
- data/lib/sisimai/reason/expired.rb +5 -9
- data/lib/sisimai/reason/feedback.rb +1 -3
- data/lib/sisimai/reason/filtered.rb +19 -38
- data/lib/sisimai/reason/hasmoved.rb +5 -8
- data/lib/sisimai/reason/hostunknown.rb +11 -18
- data/lib/sisimai/reason/mailboxfull.rb +14 -24
- data/lib/sisimai/reason/mailererror.rb +3 -5
- data/lib/sisimai/reason/mesgtoobig.rb +15 -25
- data/lib/sisimai/reason/networkerror.rb +8 -10
- data/lib/sisimai/reason/norelaying.rb +9 -14
- data/lib/sisimai/reason/notaccept.rb +9 -21
- data/lib/sisimai/reason/onhold.rb +3 -8
- data/lib/sisimai/reason/policyviolation.rb +8 -10
- data/lib/sisimai/reason/rejected.rb +36 -49
- data/lib/sisimai/reason/securityerror.rb +11 -13
- data/lib/sisimai/reason/spamdetected.rb +23 -37
- data/lib/sisimai/reason/suspend.rb +9 -10
- data/lib/sisimai/reason/syntaxerror.rb +3 -4
- data/lib/sisimai/reason/systemerror.rb +7 -9
- data/lib/sisimai/reason/systemfull.rb +2 -4
- data/lib/sisimai/reason/toomanyconn.rb +17 -30
- data/lib/sisimai/reason/undefined.rb +1 -3
- data/lib/sisimai/reason/userunknown.rb +28 -38
- data/lib/sisimai/reason/vacation.rb +4 -6
- data/lib/sisimai/reason/virusdetected.rb +4 -6
- data/lib/sisimai/rfc2606.rb +1 -2
- data/lib/sisimai/rfc3464.rb +87 -101
- data/lib/sisimai/rfc3834.rb +29 -39
- data/lib/sisimai/rfc5322.rb +17 -24
- data/lib/sisimai/rhost.rb +10 -7
- data/lib/sisimai/rhost/exchangeonline.rb +124 -255
- data/lib/sisimai/rhost/franceptt.rb +2 -2
- data/lib/sisimai/rhost/godaddy.rb +12 -25
- data/lib/sisimai/rhost/googleapps.rb +82 -183
- data/lib/sisimai/smtp.rb +4 -4
- data/lib/sisimai/smtp/error.rb +8 -8
- data/lib/sisimai/smtp/reply.rb +1 -1
- data/lib/sisimai/smtp/status.rb +1 -0
- data/lib/sisimai/string.rb +5 -7
- data/lib/sisimai/version.rb +1 -1
- data/set-of-emails/README.md +1 -1
- data/set-of-emails/maildir/bsd/README.md +50 -50
- data/sisimai-java.gemspec +1 -1
- data/sisimai.gemspec +1 -1
- metadata +4 -4
- data/lib/sisimai/skeleton.rb +0 -43
@@ -7,23 +7,20 @@ module Sisimai::Bite::Email
|
|
7
7
|
# MTA module for qmail clones
|
8
8
|
require 'sisimai/bite/email'
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
)
|
15
|
-
}xi,
|
16
|
-
:received => %r/\A[(]qmail[ ]+\d+[ ]+invoked[ ]+for[ ]+bounce[)]/,
|
10
|
+
Indicators = Sisimai::Bite::Email.INDICATORS
|
11
|
+
StartingOf = {
|
12
|
+
error: ['Remote host said:'],
|
13
|
+
rfc822: ['--- Below this line is a copy of the message.', '--- Original message follows.'],
|
17
14
|
}.freeze
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
:
|
15
|
+
MarkingsOf = {
|
16
|
+
# qmail-remote.c:248| if (code >= 500) {
|
17
|
+
# qmail-remote.c:249| out("h"); outhost(); out(" does not like recipient.\n");
|
18
|
+
# qmail-remote.c:265| if (code >= 500) quit("D"," failed on DATA command");
|
19
|
+
# qmail-remote.c:271| if (code >= 500) quit("D"," failed after I sent the message");
|
20
|
+
#
|
21
|
+
# Characters: K,Z,D in qmail-qmqpc.c, qmail-send.c, qmail-rspawn.c
|
22
|
+
# K = success, Z = temporary error, D = permanent error
|
23
|
+
message: %r{\A(?>
|
27
24
|
He/Her[ ]is[ ]not.+[ ]user
|
28
25
|
|Hi[.][ ].+[ ]unable[ ]to[ ]deliver[ ]your[ ]message[ ]to[ ]
|
29
26
|
the[ ]following[ ]addresses
|
@@ -40,29 +37,22 @@ module Sisimai::Bite::Email
|
|
40
37
|
)
|
41
38
|
|We're[ ]sorry[.]
|
42
39
|
)
|
43
|
-
}
|
44
|
-
:rfc822 => %r{\A(?:
|
45
|
-
---[ ]Below[ ]this[ ]line[ ]is[ ]a[ ]copy[ ]of[ ]the[ ]message[.]
|
46
|
-
|---[ ]Original[ ]message[ ]follows[.]
|
47
|
-
)
|
48
|
-
}xi,
|
49
|
-
:error => %r/\ARemote host said:/,
|
50
|
-
:sorry => %r/\A[Ss]orry[,.][ ]/,
|
51
|
-
:endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
|
40
|
+
}x,
|
52
41
|
}.freeze
|
42
|
+
|
53
43
|
ReSMTP = {
|
54
44
|
# Error text regular expressions which defined in qmail-remote.c
|
55
45
|
# qmail-remote.c:225| if (smtpcode() != 220) quit("ZConnected to "," but greeting failed");
|
56
|
-
conn: %r/(?:Error:)?Connected
|
46
|
+
conn: %r/(?:Error:)?Connected to .+ but greeting failed[.]/,
|
57
47
|
# qmail-remote.c:231| if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
|
58
|
-
ehlo: %r/(?:Error:)?Connected
|
48
|
+
ehlo: %r/(?:Error:)?Connected to .+ but my name was rejected[.]/,
|
59
49
|
# qmail-remote.c:238| if (code >= 500) quit("DConnected to "," but sender was rejected");
|
60
50
|
# reason = rejected
|
61
|
-
mail: %r/(?:Error:)?Connected
|
51
|
+
mail: %r/(?:Error:)?Connected to .+ but sender was rejected[.]/,
|
62
52
|
# qmail-remote.c:249| out("h"); outhost(); out(" does not like recipient.\n");
|
63
53
|
# qmail-remote.c:253| out("s"); outhost(); out(" does not like recipient.\n");
|
64
54
|
# reason = userunknown
|
65
|
-
rcpt: %r/(?:Error:)?.+
|
55
|
+
rcpt: %r/(?:Error:)?.+ does not like recipient[.]/,
|
66
56
|
# qmail-remote.c:265| if (code >= 500) quit("D"," failed on DATA command");
|
67
57
|
# qmail-remote.c:266| if (code >= 400) quit("Z"," failed on DATA command");
|
68
58
|
# qmail-remote.c:271| if (code >= 500) quit("D"," failed after I sent the message");
|
@@ -106,26 +96,24 @@ module Sisimai::Bite::Email
|
|
106
96
|
)
|
107
97
|
}x,
|
108
98
|
}.freeze
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
99
|
+
|
100
|
+
# 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/
|
102
|
+
ReIsOnHold = %r/\A[^ ]+ does not like recipient[.][ ]+.+this message has been in the queue too long[.]\z/
|
103
|
+
ReCommands = %r/Sorry, no SMTP connection got far enough; most progress was ([A-Z]{4})[ ]/
|
104
|
+
ReFailures = {
|
114
105
|
# qmail-local.c:589| strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)");
|
115
106
|
# qmail-remote.c:253| out("s"); outhost(); out(" does not like recipient.\n");
|
116
|
-
userunknown: %r
|
117
|
-
no[ ]mailbox[ ]here[ ]by[ ]that[ ]name
|
118
|
-
|[ ]does[ ]not[ ]like[ ]recipient[.]
|
119
|
-
)
|
120
|
-
}x,
|
107
|
+
userunknown: %r/(?:no mailbox here by that name | does not like recipient[.])/,
|
121
108
|
# error_str.c:192| X(EDQUOT,"disk quota exceeded")
|
122
|
-
mailboxfull: %r/disk
|
109
|
+
mailboxfull: %r/disk quota exceeded/,
|
123
110
|
# qmail-qmtpd.c:233| ... result = "Dsorry, that message size exceeds my databytes limit (#5.3.4)";
|
124
111
|
# qmail-smtpd.c:391| ... out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return;
|
125
|
-
mesgtoobig: %r/Message
|
112
|
+
mesgtoobig: %r/Message size exceeds fixed maximum message size:/,
|
126
113
|
# qmail-remote.c:68| Sorry, I couldn't find any host by that name. (#4.1.2)\n"); zerodie();
|
127
114
|
# qmail-remote.c:78| Sorry, I couldn't find any host named ");
|
128
|
-
hostunknown: %r/\ASorry
|
115
|
+
hostunknown: %r/\ASorry, I couldn't find any host /,
|
116
|
+
systemfull: %r/Requested action not taken: mailbox unavailable [(]not enough free space[)]/,
|
129
117
|
systemerror: %r{(?>
|
130
118
|
bad[ ]interpreter:[ ]No[ ]such[ ]file[ ]or[ ]directory
|
131
119
|
|system[ ]error
|
@@ -138,16 +126,11 @@ module Sisimai::Bite::Email
|
|
138
126
|
|[.][ ]Although[ ]I[']m[ ]listed[ ]as[ ]a[ ]best[-]preference[ ]MX[ ]or[ ]A[ ]for[ ]that[ ]host
|
139
127
|
)
|
140
128
|
}x,
|
141
|
-
systemfull: %r/Requested action not taken: mailbox unavailable [(]not enough free space[)]/,
|
142
129
|
}.freeze
|
143
|
-
# qmail-send.c:922| ... (&dline[c],"I'm not going to try again; this message has been in the queue too long.\n")) nomem();
|
144
|
-
ReDelayed = %r/this[ ]message[ ]has[ ]been[ ]in[ ]the[ ]queue[ ]too[ ]long[.]\z/x
|
145
|
-
Indicators = Sisimai::Bite::Email.INDICATORS
|
146
130
|
|
147
131
|
def description; return 'Unknown MTA #4'; end
|
148
132
|
def smtpagent; return Sisimai::Bite.smtpagent(self); end
|
149
133
|
def headerlist; return []; end
|
150
|
-
def pattern; return Re0; end
|
151
134
|
|
152
135
|
# Parse bounce messages from Unknown MTA #4
|
153
136
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -168,9 +151,10 @@ module Sisimai::Bite::Email
|
|
168
151
|
# by qmail, see http://cr.yp.to/qmail.html
|
169
152
|
# e.g.) Received: (qmail 12345 invoked for bounce); 29 Apr 2009 12:34:56 -0000
|
170
153
|
# Subject: failure notice
|
154
|
+
tryto = %r/\A[(]qmail[ ]+\d+[ ]+invoked[ ]+for[ ]+bounce[)]/
|
171
155
|
match = 0
|
172
|
-
match += 1 if mhead['subject']
|
173
|
-
match += 1 if mhead['received'].find { |a| a =~
|
156
|
+
match += 1 if mhead['subject'].start_with?('failure notice', 'Permanent Delivery Failure')
|
157
|
+
match += 1 if mhead['received'].find { |a| a =~ tryto }
|
174
158
|
return nil if match.zero?
|
175
159
|
|
176
160
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
@@ -181,10 +165,10 @@ module Sisimai::Bite::Email
|
|
181
165
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
182
166
|
v = nil
|
183
167
|
|
184
|
-
hasdivided.
|
168
|
+
while e = hasdivided.shift do
|
185
169
|
if readcursor.zero?
|
186
170
|
# Beginning of the bounce message or delivery status part
|
187
|
-
if e =~
|
171
|
+
if e =~ MarkingsOf[:message]
|
188
172
|
readcursor |= Indicators[:deliverystatus]
|
189
173
|
next
|
190
174
|
end
|
@@ -192,7 +176,7 @@ module Sisimai::Bite::Email
|
|
192
176
|
|
193
177
|
if (readcursor & Indicators[:'message-rfc822']).zero?
|
194
178
|
# Beginning of the original message part
|
195
|
-
if e
|
179
|
+
if e.start_with?(StartingOf[:rfc822][0], StartingOf[:rfc822][1])
|
196
180
|
readcursor |= Indicators[:'message-rfc822']
|
197
181
|
next
|
198
182
|
end
|
@@ -206,7 +190,6 @@ module Sisimai::Bite::Email
|
|
206
190
|
next
|
207
191
|
end
|
208
192
|
rfc822list << e
|
209
|
-
|
210
193
|
else
|
211
194
|
# Before "message/rfc822"
|
212
195
|
next if (readcursor & Indicators[:deliverystatus]).zero?
|
@@ -232,8 +215,8 @@ module Sisimai::Bite::Email
|
|
232
215
|
# Append error message
|
233
216
|
next if e.empty?
|
234
217
|
v['diagnosis'] ||= ''
|
235
|
-
v['diagnosis']
|
236
|
-
v['alterrors']
|
218
|
+
v['diagnosis'] << e + ' '
|
219
|
+
v['alterrors'] = e if e.start_with?(StartingOf[:error][0])
|
237
220
|
|
238
221
|
next if v['rhost']
|
239
222
|
if cv = e.match(ReHost)
|
@@ -243,8 +226,8 @@ module Sisimai::Bite::Email
|
|
243
226
|
end
|
244
227
|
end
|
245
228
|
return nil if recipients.zero?
|
246
|
-
require 'sisimai/string'
|
247
229
|
|
230
|
+
require 'sisimai/string'
|
248
231
|
dscontents.map do |e|
|
249
232
|
e['agent'] = self.smtpagent
|
250
233
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
@@ -260,7 +243,7 @@ module Sisimai::Bite::Email
|
|
260
243
|
|
261
244
|
unless e['command']
|
262
245
|
# Verify each regular expression of patches
|
263
|
-
if cv = e['diagnosis'].match(
|
246
|
+
if cv = e['diagnosis'].match(ReCommands)
|
264
247
|
e['command'] = cv[1].upcase
|
265
248
|
end
|
266
249
|
e['command'] ||= ''
|
@@ -272,28 +255,26 @@ module Sisimai::Bite::Email
|
|
272
255
|
# MAIL | Connected to 192.0.2.135 but sender was rejected.
|
273
256
|
e['reason'] = 'rejected'
|
274
257
|
|
275
|
-
elsif e['command']
|
258
|
+
elsif %w[HELO EHLO].index(e['command'])
|
276
259
|
# HELO | Connected to 192.0.2.135 but my name was rejected.
|
277
260
|
e['reason'] = 'blocked'
|
278
|
-
|
279
261
|
else
|
280
262
|
# Try to match with each error message in the table
|
281
|
-
if e['diagnosis'] =~
|
263
|
+
if e['diagnosis'] =~ ReIsOnHold
|
282
264
|
# To decide the reason require pattern match with
|
283
265
|
# Sisimai::Reason::* modules
|
284
266
|
e['reason'] = 'onhold'
|
285
|
-
|
286
267
|
else
|
287
|
-
|
268
|
+
ReFailures.each_key do |r|
|
288
269
|
# Verify each regular expression of session errors
|
289
270
|
if e['alterrors']
|
290
271
|
# Check the value of "alterrors"
|
291
|
-
next unless e['alterrors'] =~
|
272
|
+
next unless e['alterrors'] =~ ReFailures[r]
|
292
273
|
e['reason'] = r.to_s
|
293
274
|
end
|
294
275
|
break if e['reason']
|
295
276
|
|
296
|
-
next unless e['diagnosis'] =~
|
277
|
+
next unless e['diagnosis'] =~ ReFailures[r]
|
297
278
|
e['reason'] = r.to_s
|
298
279
|
break
|
299
280
|
end
|
@@ -308,7 +289,7 @@ module Sisimai::Bite::Email
|
|
308
289
|
end
|
309
290
|
|
310
291
|
unless e['reason']
|
311
|
-
e['reason'] = 'expired' if e['diagnosis'] =~
|
292
|
+
e['reason'] = 'expired' if e['diagnosis'] =~ ReDelaying
|
312
293
|
end
|
313
294
|
end
|
314
295
|
end
|
@@ -6,21 +6,15 @@ module Sisimai::Bite::Email
|
|
6
6
|
# Imported from p5-Sisimail/lib/Sisimai/Bite/Email/X5.pm
|
7
7
|
require 'sisimai/bite/email'
|
8
8
|
|
9
|
-
Re0 = {
|
10
|
-
:from => %r/\bTWFpbCBEZWxpdmVyeSBTdWJzeXN0ZW0\b/,
|
11
|
-
:to => %r/\bNotificationRecipients\b/,
|
12
|
-
}.freeze
|
13
|
-
Re1 = {
|
14
|
-
:begin => %r|\AContent-Type: message/delivery-status|,
|
15
|
-
:rfc822 => %r|\AContent-Type: message/rfc822|,
|
16
|
-
:endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
|
17
|
-
}.freeze
|
18
9
|
Indicators = Sisimai::Bite::Email.INDICATORS
|
10
|
+
StartingOf = {
|
11
|
+
message: ['Content-Type: message/delivery-status'],
|
12
|
+
rfc822: ['Content-Type: message/rfc822'],
|
13
|
+
}.freeze
|
19
14
|
|
20
15
|
def description; return 'Unknown MTA #5'; end
|
21
16
|
def smtpagent; return Sisimai::Bite.smtpagent(self); end
|
22
17
|
def headerlist; return []; end
|
23
|
-
def pattern; return Re0; end
|
24
18
|
|
25
19
|
# Parse bounce messages from Unknown MTA #5
|
26
20
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -36,19 +30,17 @@ module Sisimai::Bite::Email
|
|
36
30
|
def scan(mhead, mbody)
|
37
31
|
return nil unless mhead
|
38
32
|
return nil unless mbody
|
39
|
-
match = 0
|
40
|
-
|
41
|
-
# To: "NotificationRecipients" <...>
|
42
|
-
match += 1 if mhead['to'] && mhead['to'] =~ Re0[:to]
|
43
|
-
|
44
33
|
require 'sisimai/mime'
|
45
|
-
|
34
|
+
|
35
|
+
match = 0
|
36
|
+
match += 1 if mhead['to'].to_s.include?('NotificationRecipients')
|
37
|
+
if mhead['from'].include?('TWFpbCBEZWxpdmVyeSBTdWJzeXN0ZW0')
|
46
38
|
# From: "=?iso-2022-jp?B?TWFpbCBEZWxpdmVyeSBTdWJzeXN0ZW0=?=" <...>
|
47
39
|
# Mail Delivery Subsystem
|
48
40
|
mhead['from'].split(' ').each do |f|
|
49
41
|
# Check each element of From: header
|
50
42
|
next unless Sisimai::MIME.is_mimeencoded(f)
|
51
|
-
match += 1 if Sisimai::MIME.mimedecode([f])
|
43
|
+
match += 1 if Sisimai::MIME.mimedecode([f]).include?('Mail Delivery Subsystem')
|
52
44
|
break
|
53
45
|
end
|
54
46
|
end
|
@@ -56,7 +48,7 @@ module Sisimai::Bite::Email
|
|
56
48
|
if Sisimai::MIME.is_mimeencoded(mhead['subject'])
|
57
49
|
# Subject: =?iso-2022-jp?B?UmV0dXJuZWQgbWFpbDogVXNlciB1bmtub3du?=
|
58
50
|
plain = Sisimai::MIME.mimedecode([mhead['subject']])
|
59
|
-
match += 1 if plain
|
51
|
+
match += 1 if plain.include?('Mail Delivery Subsystem')
|
60
52
|
end
|
61
53
|
return nil if match < 2
|
62
54
|
|
@@ -69,14 +61,14 @@ module Sisimai::Bite::Email
|
|
69
61
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
70
62
|
v = nil
|
71
63
|
|
72
|
-
hasdivided.
|
64
|
+
while e = hasdivided.shift do
|
73
65
|
# Save the current line for the next loop
|
74
66
|
havepassed << e
|
75
67
|
p = havepassed[-2]
|
76
68
|
|
77
69
|
if readcursor.zero?
|
78
70
|
# Beginning of the bounce message or delivery status part
|
79
|
-
if e
|
71
|
+
if e.start_with?(StartingOf[:message][0])
|
80
72
|
readcursor |= Indicators[:deliverystatus]
|
81
73
|
next
|
82
74
|
end
|
@@ -84,7 +76,7 @@ module Sisimai::Bite::Email
|
|
84
76
|
|
85
77
|
if (readcursor & Indicators[:'message-rfc822']).zero?
|
86
78
|
# Beginning of the original message part
|
87
|
-
if e
|
79
|
+
if e.start_with?(StartingOf[:rfc822][0])
|
88
80
|
readcursor |= Indicators[:'message-rfc822']
|
89
81
|
next
|
90
82
|
end
|
@@ -95,7 +87,7 @@ module Sisimai::Bite::Email
|
|
95
87
|
next if e.empty?
|
96
88
|
v = dscontents[-1]
|
97
89
|
|
98
|
-
if cv = e.match(/\
|
90
|
+
if cv = e.match(/\AFinal-Recipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/)
|
99
91
|
# Final-Recipient: RFC822; kijitora@example.jp
|
100
92
|
if v['recipient']
|
101
93
|
# There are multiple recipient addresses in the message body.
|
@@ -105,44 +97,42 @@ module Sisimai::Bite::Email
|
|
105
97
|
v['recipient'] = cv[1]
|
106
98
|
recipients += 1
|
107
99
|
|
108
|
-
elsif cv = e.match(/\
|
109
|
-
e.match(/\
|
100
|
+
elsif cv = e.match(/\AX-Actual-Recipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/) ||
|
101
|
+
e.match(/\AOriginal-Recipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/)
|
110
102
|
# X-Actual-Recipient: RFC822; kijitora@example.co.jp
|
111
103
|
# Original-Recipient: rfc822;kijitora@example.co.jp
|
112
104
|
v['alias'] = cv[1]
|
113
105
|
|
114
|
-
elsif cv = e.match(/\
|
106
|
+
elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
|
115
107
|
# Action: failed
|
116
108
|
v['action'] = cv[1].downcase
|
117
109
|
|
118
|
-
elsif cv = e.match(/\
|
110
|
+
elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
|
119
111
|
# Status: 5.1.1
|
120
112
|
v['status'] = cv[1]
|
121
113
|
|
122
|
-
elsif cv = e.match(/\
|
114
|
+
elsif cv = e.match(/\AReporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
123
115
|
# Reporting-MTA: dns; mx.example.jp
|
124
116
|
v['lhost'] = cv[1].downcase
|
125
117
|
|
126
|
-
elsif cv = e.match(/\
|
118
|
+
elsif cv = e.match(/\ARemote-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
127
119
|
# Remote-MTA: DNS; mx.example.jp
|
128
120
|
v['rhost'] = cv[1].downcase
|
129
121
|
|
130
|
-
elsif cv = e.match(/\
|
122
|
+
elsif cv = e.match(/\ALast-Attempt-Date:[ ]*(.+)\z/)
|
131
123
|
# Last-Attempt-Date: Fri, 14 Feb 2014 12:30:08 -0500
|
132
124
|
v['date'] = cv[1]
|
133
|
-
|
134
125
|
else
|
135
126
|
# Get an error message from Diagnostic-Code: field
|
136
|
-
if cv = e.match(/\
|
127
|
+
if cv = e.match(/\ADiagnostic-Code:[ ]*(.+?);[ ]*(.+)\z/)
|
137
128
|
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
138
129
|
v['spec'] = cv[1].downcase
|
139
130
|
v['diagnosis'] = cv[2]
|
140
131
|
|
141
|
-
elsif p
|
132
|
+
elsif p.start_with?('Diagnostic-Code:') && cv = e.match(/\A[ \t]+(.+)\z/)
|
142
133
|
# Continued line of the value of Diagnostic-Code header
|
143
|
-
v['diagnosis']
|
144
|
-
|
145
|
-
havepassed[-1] = 'Diagnostic-Code: ' + e
|
134
|
+
v['diagnosis'] << ' ' << cv[1]
|
135
|
+
havepassed[-1] = 'Diagnostic-Code: ' << e
|
146
136
|
end
|
147
137
|
end
|
148
138
|
else
|
@@ -156,12 +146,11 @@ module Sisimai::Bite::Email
|
|
156
146
|
next
|
157
147
|
end
|
158
148
|
rfc822list << e
|
159
|
-
|
160
149
|
end
|
161
150
|
end
|
162
151
|
return nil if recipients.zero?
|
163
|
-
require 'sisimai/string'
|
164
152
|
|
153
|
+
require 'sisimai/string'
|
165
154
|
dscontents.map do |e|
|
166
155
|
e['agent'] = self.smtpagent
|
167
156
|
e['diagnosis'] ||= Sisimai::String.sweep(e['diagnosis'])
|
@@ -6,15 +6,11 @@ module Sisimai::Bite::Email
|
|
6
6
|
# Imported from p5-Sisimail/lib/Sisimai/Bite/Email/Yahoo.pm
|
7
7
|
require 'sisimai/bite/email'
|
8
8
|
|
9
|
-
Re0 = {
|
10
|
-
:subject => %r/\AFailure Notice\z/,
|
11
|
-
}.freeze
|
12
|
-
Re1 = {
|
13
|
-
:begin => %r/\ASorry, we were unable to deliver your message/,
|
14
|
-
:rfc822 => %r/\A--- Below this line is a copy of the message[.]\z/,
|
15
|
-
:endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
|
16
|
-
}.freeze
|
17
9
|
Indicators = Sisimai::Bite::Email.INDICATORS
|
10
|
+
StartingOf = {
|
11
|
+
message: ['Sorry, we were unable to deliver your message'],
|
12
|
+
rfc822: ['--- Below this line is a copy of the message.'],
|
13
|
+
}.freeze
|
18
14
|
|
19
15
|
def description; return 'Yahoo! MAIL: https://www.yahoo.com'; end
|
20
16
|
def smtpagent; return Sisimai::Bite.smtpagent(self); end
|
@@ -24,7 +20,6 @@ module Sisimai::Bite::Email
|
|
24
20
|
# X-YMail-OSG: bTIbpDEVM1lHz...
|
25
21
|
# X-Originating-IP: [192.0.2.9]
|
26
22
|
def headerlist; return ['X-YMailISG']; end
|
27
|
-
def pattern; return Re0; end
|
28
23
|
|
29
24
|
# Parse bounce messages from Yahoo! MAIL
|
30
25
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -40,6 +35,8 @@ module Sisimai::Bite::Email
|
|
40
35
|
def scan(mhead, mbody)
|
41
36
|
return nil unless mhead
|
42
37
|
return nil unless mbody
|
38
|
+
|
39
|
+
# :subject => %r/\AFailure Notice\z/,
|
43
40
|
return nil unless mhead['x-ymailisg']
|
44
41
|
|
45
42
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
@@ -50,10 +47,10 @@ module Sisimai::Bite::Email
|
|
50
47
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
51
48
|
v = nil
|
52
49
|
|
53
|
-
hasdivided.
|
50
|
+
while e = hasdivided.shift do
|
54
51
|
if readcursor.zero?
|
55
52
|
# Beginning of the bounce message or delivery status part
|
56
|
-
if e
|
53
|
+
if e.start_with?(StartingOf[:message][0])
|
57
54
|
readcursor |= Indicators[:deliverystatus]
|
58
55
|
next
|
59
56
|
end
|
@@ -61,7 +58,7 @@ module Sisimai::Bite::Email
|
|
61
58
|
|
62
59
|
if (readcursor & Indicators[:'message-rfc822']).zero?
|
63
60
|
# Beginning of the original message part
|
64
|
-
if e
|
61
|
+
if e == StartingOf[:rfc822][0]
|
65
62
|
readcursor |= Indicators[:'message-rfc822']
|
66
63
|
next
|
67
64
|
end
|
@@ -75,7 +72,6 @@ module Sisimai::Bite::Email
|
|
75
72
|
next
|
76
73
|
end
|
77
74
|
rfc822list << e
|
78
|
-
|
79
75
|
else
|
80
76
|
# Before "message/rfc822"
|
81
77
|
next if (readcursor & Indicators[:deliverystatus]).zero?
|
@@ -96,7 +92,6 @@ module Sisimai::Bite::Email
|
|
96
92
|
end
|
97
93
|
v['recipient'] = cv[1]
|
98
94
|
recipients += 1
|
99
|
-
|
100
95
|
else
|
101
96
|
if e.start_with?('Remote host said:')
|
102
97
|
# Remote host said: 550 5.1.1 <kijitora@example.org>... User Unknown [RCPT_TO]
|
@@ -106,13 +101,12 @@ module Sisimai::Bite::Email
|
|
106
101
|
# Get SMTP command from the value of "Remote host said:"
|
107
102
|
v['command'] = cv[1]
|
108
103
|
end
|
109
|
-
|
110
104
|
else
|
111
105
|
# <mailboxfull@example.jp>:
|
112
106
|
# Remote host said:
|
113
107
|
# 550 5.2.2 <mailboxfull@example.jp>... Mailbox Full
|
114
108
|
# [RCPT_TO]
|
115
|
-
if v['diagnosis']
|
109
|
+
if v['diagnosis'].start_with?('Remote host said:')
|
116
110
|
# Remote host said:
|
117
111
|
# 550 5.2.2 <mailboxfull@example.jp>... Mailbox Full
|
118
112
|
if cv = e.match(/\[([A-Z]{4}).*\]\z/)
|
@@ -123,15 +117,13 @@ module Sisimai::Bite::Email
|
|
123
117
|
v['diagnosis'] = e
|
124
118
|
end
|
125
119
|
end
|
126
|
-
|
127
120
|
end
|
128
|
-
|
129
121
|
end
|
130
122
|
end
|
131
123
|
end
|
132
124
|
return nil if recipients.zero?
|
133
|
-
require 'sisimai/string'
|
134
125
|
|
126
|
+
require 'sisimai/string'
|
135
127
|
dscontents.map do |e|
|
136
128
|
e['diagnosis'] = e['diagnosis'].gsub(/\\n/, ' ')
|
137
129
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|