sisimai 4.24.1-java → 4.25.0-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 +3 -2
- data/ANALYTICAL-PRECISION +16 -25
- data/ChangeLog.md +41 -0
- data/Developers.mk +2 -2
- data/README-JA.md +13 -13
- data/README.md +13 -13
- data/lib/sisimai.rb +3 -7
- data/lib/sisimai/address.rb +25 -41
- data/lib/sisimai/arf.rb +58 -59
- data/lib/sisimai/bite.rb +0 -1
- data/lib/sisimai/bite/email.rb +7 -7
- data/lib/sisimai/bite/email/activehunter.rb +4 -3
- data/lib/sisimai/bite/email/amavis.rb +133 -0
- data/lib/sisimai/bite/email/amazonses.rb +53 -87
- data/lib/sisimai/bite/email/amazonworkmail.rb +51 -57
- data/lib/sisimai/bite/email/aol.rb +50 -76
- data/lib/sisimai/bite/email/apachejames.rb +2 -2
- data/lib/sisimai/bite/email/bigfoot.rb +47 -74
- data/lib/sisimai/bite/email/biglobe.rb +8 -9
- data/lib/sisimai/bite/email/courier.rb +56 -101
- data/lib/sisimai/bite/email/domino.rb +7 -8
- data/lib/sisimai/bite/email/einsundeins.rb +4 -5
- data/lib/sisimai/bite/email/exchange2003.rb +21 -22
- data/lib/sisimai/bite/email/exchange2007.rb +26 -28
- data/lib/sisimai/bite/email/exim.rb +48 -47
- data/lib/sisimai/bite/email/ezweb.rb +24 -36
- data/lib/sisimai/bite/email/facebook.rb +54 -79
- data/lib/sisimai/bite/email/fml.rb +10 -10
- data/lib/sisimai/bite/email/gmx.rb +6 -6
- data/lib/sisimai/bite/email/google.rb +12 -13
- data/lib/sisimai/bite/email/gsuite.rb +80 -108
- data/lib/sisimai/bite/email/imailserver.rb +16 -16
- data/lib/sisimai/bite/email/interscanmss.rb +4 -6
- data/lib/sisimai/bite/email/kddi.rb +9 -11
- data/lib/sisimai/bite/email/mailfoundry.rb +2 -2
- data/lib/sisimai/bite/email/mailmarshalsmtp.rb +2 -2
- data/lib/sisimai/bite/email/mailru.rb +12 -13
- data/lib/sisimai/bite/email/mcafee.rb +31 -25
- data/lib/sisimai/bite/email/messagelabs.rb +48 -87
- data/lib/sisimai/bite/email/messagingserver.rb +9 -10
- data/lib/sisimai/bite/email/mfilter.rb +16 -16
- data/lib/sisimai/bite/email/mxlogic.rb +11 -11
- data/lib/sisimai/bite/email/notes.rb +5 -6
- data/lib/sisimai/bite/email/office365.rb +25 -42
- data/lib/sisimai/bite/email/opensmtpd.rb +8 -8
- data/lib/sisimai/bite/email/outlook.rb +49 -67
- data/lib/sisimai/bite/email/postfix.rb +78 -112
- data/lib/sisimai/bite/email/qmail.rb +23 -23
- data/lib/sisimai/bite/email/receivingses.rb +53 -86
- data/lib/sisimai/bite/email/sendgrid.rb +65 -84
- data/lib/sisimai/bite/email/sendmail.rb +89 -117
- data/lib/sisimai/bite/email/surfcontrol.rb +15 -18
- data/lib/sisimai/bite/email/userdefined.rb +1 -1
- data/lib/sisimai/bite/email/v5sendmail.rb +3 -4
- data/lib/sisimai/bite/email/verizon.rb +7 -8
- data/lib/sisimai/bite/email/x1.rb +2 -2
- data/lib/sisimai/bite/email/x2.rb +2 -2
- data/lib/sisimai/bite/email/x3.rb +3 -3
- data/lib/sisimai/bite/email/x4.rb +22 -22
- data/lib/sisimai/bite/email/x5.rb +40 -49
- data/lib/sisimai/bite/email/yahoo.rb +3 -3
- data/lib/sisimai/bite/email/yandex.rb +54 -82
- data/lib/sisimai/bite/email/zoho.rb +6 -6
- data/lib/sisimai/bite/json/amazonses.rb +20 -20
- data/lib/sisimai/bite/json/sendgrid.rb +2 -2
- data/lib/sisimai/data.rb +27 -40
- data/lib/sisimai/datetime.rb +146 -162
- data/lib/sisimai/mda.rb +30 -31
- data/lib/sisimai/message/email.rb +83 -123
- data/lib/sisimai/message/json.rb +2 -4
- data/lib/sisimai/mime.rb +31 -34
- data/lib/sisimai/order/email.rb +23 -22
- data/lib/sisimai/reason.rb +61 -61
- data/lib/sisimai/reason/blocked.rb +139 -135
- data/lib/sisimai/reason/contenterror.rb +11 -10
- data/lib/sisimai/reason/exceedlimit.rb +4 -4
- data/lib/sisimai/reason/expired.rb +20 -20
- data/lib/sisimai/reason/filtered.rb +19 -18
- data/lib/sisimai/reason/hasmoved.rb +3 -3
- data/lib/sisimai/reason/hostunknown.rb +19 -19
- data/lib/sisimai/reason/mailboxfull.rb +49 -49
- data/lib/sisimai/reason/mailererror.rb +16 -16
- data/lib/sisimai/reason/mesgtoobig.rb +17 -17
- data/lib/sisimai/reason/networkerror.rb +19 -19
- data/lib/sisimai/reason/norelaying.rb +16 -16
- data/lib/sisimai/reason/notaccept.rb +9 -10
- data/lib/sisimai/reason/onhold.rb +1 -1
- data/lib/sisimai/reason/policyviolation.rb +21 -20
- data/lib/sisimai/reason/rejected.rb +53 -53
- data/lib/sisimai/reason/securityerror.rb +29 -29
- data/lib/sisimai/reason/spamdetected.rb +127 -127
- data/lib/sisimai/reason/suspend.rb +17 -17
- data/lib/sisimai/reason/systemerror.rb +22 -21
- data/lib/sisimai/reason/systemfull.rb +6 -6
- data/lib/sisimai/reason/toomanyconn.rb +19 -18
- data/lib/sisimai/reason/userunknown.rb +122 -121
- data/lib/sisimai/reason/vacation.rb +8 -8
- data/lib/sisimai/reason/virusdetected.rb +8 -8
- data/lib/sisimai/rfc1894.rb +142 -0
- data/lib/sisimai/rfc3464.rb +70 -70
- data/lib/sisimai/rfc3834.rb +15 -15
- data/lib/sisimai/rfc5322.rb +20 -36
- data/lib/sisimai/rhost.rb +1 -0
- data/lib/sisimai/rhost/exchangeonline.rb +31 -33
- data/lib/sisimai/rhost/franceptt.rb +23 -23
- data/lib/sisimai/rhost/godaddy.rb +28 -28
- data/lib/sisimai/rhost/googleapps.rb +39 -41
- data/lib/sisimai/rhost/kddi.rb +3 -3
- data/lib/sisimai/rhost/tencentqq.rb +51 -0
- data/lib/sisimai/smtp/error.rb +14 -21
- data/lib/sisimai/smtp/reply.rb +14 -13
- data/lib/sisimai/smtp/status.rb +178 -179
- data/lib/sisimai/string.rb +13 -12
- data/lib/sisimai/version.rb +1 -1
- data/set-of-emails/README.md +1 -5
- data/set-of-emails/maildir/bsd/arf-23.eml +49 -0
- data/set-of-emails/maildir/bsd/email-amavis-01.eml +78 -0
- data/set-of-emails/maildir/bsd/email-amavis-02.eml +78 -0
- data/set-of-emails/maildir/bsd/email-exchange2007-04.eml +146 -0
- data/set-of-emails/maildir/bsd/email-exim-60.eml +94 -0
- data/set-of-emails/maildir/bsd/email-ezweb-08.eml +49 -0
- data/set-of-emails/maildir/bsd/email-google-19.eml +67 -0
- data/set-of-emails/maildir/bsd/email-mcafee-05.eml +74 -0
- data/set-of-emails/maildir/bsd/email-messagingserver-12.eml +99 -0
- data/set-of-emails/maildir/bsd/email-postfix-46.eml +81 -0
- data/set-of-emails/maildir/bsd/email-postfix-47.eml +79 -0
- data/set-of-emails/maildir/bsd/email-postfix-48.eml +79 -0
- data/set-of-emails/maildir/bsd/email-postfix-49.eml +141 -0
- data/set-of-emails/maildir/bsd/email-postfix-50.eml +143 -0
- data/set-of-emails/maildir/bsd/email-postfix-51.eml +73 -0
- data/set-of-emails/maildir/bsd/email-postfix-52.eml +79 -0
- data/set-of-emails/maildir/bsd/email-postfix-53.eml +76 -0
- data/set-of-emails/maildir/bsd/email-postfix-54.eml +73 -0
- data/set-of-emails/maildir/bsd/email-postfix-55.eml +74 -0
- data/set-of-emails/maildir/bsd/email-postfix-56.eml +78 -0
- data/set-of-emails/maildir/bsd/email-qmail-10.eml +50 -0
- data/set-of-emails/maildir/bsd/email-x2-05.eml +38 -0
- data/set-of-emails/maildir/bsd/rhost-google-apps-02.eml +88 -0
- data/set-of-emails/maildir/bsd/rhost-tencentqq-01.eml +84 -0
- data/set-of-emails/maildir/bsd/rhost-tencentqq-02.eml +84 -0
- data/set-of-emails/maildir/bsd/rhost-tencentqq-03.eml +81 -0
- data/set-of-emails/maildir/dos/email-amavis-01.eml +78 -0
- data/set-of-emails/maildir/dos/email-apachejames-01.eml +1 -2
- data/set-of-emails/maildir/dos/email-messagelabs-01.eml +67 -50
- data/set-of-emails/maildir/dos/email-x4-01.eml +31 -76
- data/set-of-emails/maildir/dos/rhost-tencentqq-01.eml +84 -0
- data/set-of-emails/maildir/mac/email-amavis-01.eml +1 -4
- data/set-of-emails/maildir/mac/email-apachejames-01.eml +1 -9
- data/set-of-emails/maildir/mac/email-messagelabs-01.eml +1 -9
- data/set-of-emails/maildir/mac/email-x4-01.eml +1 -5
- data/set-of-emails/maildir/mac/rhost-tencentqq-01.eml +1 -4
- metadata +35 -4
- data/set-of-emails/logo/horizontalversions.png +0 -0
- data/set-of-emails/logo/icon.png +0 -0
@@ -17,7 +17,7 @@ module Sisimai::Bite::Email
|
|
17
17
|
|
18
18
|
# Return-Path: <apps@sendgrid.net>
|
19
19
|
# X-Mailer: MIME-tools 5.502 (Entity 5.502)
|
20
|
-
def headerlist; return [
|
20
|
+
def headerlist; return %w[return-path x-mailer]; end
|
21
21
|
|
22
22
|
# Parse bounce messages from SendGrid
|
23
23
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -36,6 +36,10 @@ module Sisimai::Bite::Email
|
|
36
36
|
return nil unless mhead['return-path'] == '<apps@sendgrid.net>'
|
37
37
|
return nil unless mhead['subject'] == 'Undelivered Mail Returned to Sender'
|
38
38
|
|
39
|
+
require 'sisimai/rfc1894'
|
40
|
+
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
41
|
+
permessage = {} # (Hash) Store values of each Per-Message field
|
42
|
+
|
39
43
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
40
44
|
hasdivided = mbody.split("\n")
|
41
45
|
havepassed = ['']
|
@@ -44,10 +48,6 @@ module Sisimai::Bite::Email
|
|
44
48
|
readcursor = 0 # (Integer) Points the current cursor position
|
45
49
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
46
50
|
commandtxt = '' # (String) SMTP Command name begin with the string '>>>'
|
47
|
-
connvalues = 0 # (Integer) Flag, 1 if all the value of connheader have been set
|
48
|
-
connheader = {
|
49
|
-
'date' => '', # The value of Arrival-Date header
|
50
|
-
}
|
51
51
|
v = nil
|
52
52
|
|
53
53
|
while e = hasdivided.shift do
|
@@ -56,7 +56,7 @@ module Sisimai::Bite::Email
|
|
56
56
|
p = havepassed[-2]
|
57
57
|
|
58
58
|
if readcursor == 0
|
59
|
-
# Beginning of the bounce message or delivery
|
59
|
+
# Beginning of the bounce message or message/delivery-status part
|
60
60
|
if e == StartingOf[:message][0]
|
61
61
|
readcursor |= Indicators[:deliverystatus]
|
62
62
|
next
|
@@ -64,7 +64,7 @@ module Sisimai::Bite::Email
|
|
64
64
|
end
|
65
65
|
|
66
66
|
if (readcursor & Indicators[:'message-rfc822']) == 0
|
67
|
-
# Beginning of the original message part
|
67
|
+
# Beginning of the original message part(message/rfc822)
|
68
68
|
if e == StartingOf[:rfc822][0]
|
69
69
|
readcursor |= Indicators[:'message-rfc822']
|
70
70
|
next
|
@@ -72,7 +72,7 @@ module Sisimai::Bite::Email
|
|
72
72
|
end
|
73
73
|
|
74
74
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
75
|
-
#
|
75
|
+
# message/rfc822 OR text/rfc822-headers part
|
76
76
|
if e.empty?
|
77
77
|
blanklines += 1
|
78
78
|
break if blanklines > 1
|
@@ -80,97 +80,79 @@ module Sisimai::Bite::Email
|
|
80
80
|
end
|
81
81
|
rfc822list << e
|
82
82
|
else
|
83
|
-
#
|
83
|
+
# message/delivery-status part
|
84
84
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
85
85
|
next if e.empty?
|
86
86
|
|
87
|
-
if
|
88
|
-
#
|
89
|
-
|
90
|
-
# Action: failed
|
91
|
-
# Status: 5.1.1
|
92
|
-
# Diagnostic-Code: 550 5.1.1 <kijitora@example.jp>... User Unknown
|
87
|
+
if f = Sisimai::RFC1894.match(e)
|
88
|
+
# "e" matched with any field defined in RFC3464
|
89
|
+
o = Sisimai::RFC1894.field(e)
|
93
90
|
v = dscontents[-1]
|
94
91
|
|
95
|
-
|
96
|
-
#
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
recipients += 1
|
104
|
-
|
105
|
-
elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
|
106
|
-
# Action: failed
|
107
|
-
v['action'] = cv[1].downcase
|
108
|
-
|
109
|
-
elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
|
110
|
-
# Status: 5.1.1
|
111
|
-
# Status:5.2.0
|
112
|
-
# Status: 5.1.0 (permanent failure)
|
113
|
-
v['status'] = cv[1]
|
92
|
+
unless o
|
93
|
+
# Fallback code for empty value or invalid formatted value
|
94
|
+
# - Status: (empty)
|
95
|
+
# - Diagnostic-Code: 550 5.1.1 ... (No "diagnostic-type" sub field)
|
96
|
+
next unless cv = e.match(/\ADiagnostic-Code:[ ]*(.+)/)
|
97
|
+
v['diagnosis'] = cv[1]
|
98
|
+
next;
|
99
|
+
end
|
114
100
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
101
|
+
if o[-1] == 'addr'
|
102
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
103
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
104
|
+
if o[0] == 'final-recipient'
|
105
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
106
|
+
if v['recipient']
|
107
|
+
# There are multiple recipient addresses in the message body.
|
108
|
+
dscontents << Sisimai::Bite.DELIVERYSTATUS
|
109
|
+
v = dscontents[-1]
|
110
|
+
end
|
111
|
+
v['recipient'] = o[2]
|
112
|
+
recipients += 1
|
113
|
+
else
|
114
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
115
|
+
v['alias'] = o[2]
|
124
116
|
end
|
117
|
+
elsif o[-1] == 'code'
|
118
|
+
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
119
|
+
v['spec'] = o[1]
|
120
|
+
v['diagnosis'] = o[2]
|
121
|
+
elsif o[-1] == 'date'
|
122
|
+
# Arrival-Date: 2012-12-31 23-59-59
|
123
|
+
next unless cv = e.match(/\AArrival-Date: (\d{4})[-](\d{2})[-](\d{2}) (\d{2})[-](\d{2})[-](\d{2})\z/)
|
124
|
+
o[1] << 'Thu, ' << cv[3] + ' '
|
125
|
+
o[1] << Sisimai::DateTime.monthname(0)[cv[2].to_i - 1]
|
126
|
+
o[1] << ' ' << cv[1] + ' ' << [cv[4], cv[5], cv[6]].join(':')
|
127
|
+
o[1] << ' ' << Sisimai::DateTime.abbr2tz('CDT')
|
128
|
+
else
|
129
|
+
# Other DSN fields defined in RFC3464
|
130
|
+
next unless fieldtable.key?(o[0])
|
131
|
+
v[fieldtable[o[0]]] = o[2]
|
132
|
+
|
133
|
+
next unless f == 1
|
134
|
+
permessage[fieldtable[o[0]]] = o[2]
|
125
135
|
end
|
126
136
|
else
|
127
|
-
#
|
128
|
-
#
|
129
|
-
# I'm sorry to have to tell you that your message was not able to be
|
130
|
-
# delivered to one of its intended recipients.
|
131
|
-
#
|
132
|
-
# If you require assistance with this, please contact SendGrid support.
|
133
|
-
#
|
134
|
-
# shironekochan:000000:<kijitora@example.jp> : 192.0.2.250 : mx.example.jp:[192.0.2.153] :
|
135
|
-
# 550 5.1.1 <userunknown@cubicroot.jp>... User Unknown in RCPT TO
|
136
|
-
#
|
137
|
-
# ------------=_1351676802-30315-116783
|
138
|
-
# Content-Type: message/delivery-status
|
139
|
-
# Content-Disposition: inline
|
140
|
-
# Content-Transfer-Encoding: 7bit
|
141
|
-
# Content-Description: Delivery Report
|
142
|
-
#
|
143
|
-
# X-SendGrid-QueueID: 959479146
|
144
|
-
# X-SendGrid-Sender: <bounces+61689-10be-kijitora=example.jp@sendgrid.info>
|
145
|
-
# Arrival-Date: 2012-12-31 23-59-59
|
137
|
+
# The line does not begin with a DSN field defined in RFC3464
|
146
138
|
if cv = e.match(/.+ in (?:End of )?([A-Z]{4}).*\z/)
|
147
139
|
# in RCPT TO, in MAIL FROM, end of DATA
|
148
140
|
commandtxt = cv[1]
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
next unless
|
153
|
-
|
154
|
-
|
155
|
-
if cv = e.match(/\AArrival-Date: (\d{4})[-](\d{2})[-](\d{2}) (\d{2})[-](\d{2})[-](\d{2})\z/)
|
156
|
-
# Arrival-Date: 2011-08-12 01-05-05
|
157
|
-
arrivaldate << 'Thu, ' << cv[3] + ' '
|
158
|
-
arrivaldate << Sisimai::DateTime.monthname(0)[cv[2].to_i - 1]
|
159
|
-
arrivaldate << ' ' << cv[1] + ' ' << [cv[4], cv[5], cv[6]].join(':')
|
160
|
-
arrivaldate << ' ' << Sisimai::DateTime.abbr2tz('CDT')
|
161
|
-
end
|
162
|
-
connheader['date'] = arrivaldate
|
163
|
-
connvalues += 1
|
141
|
+
else
|
142
|
+
# Continued line of the value of Diagnostic-Code field
|
143
|
+
next unless p.start_with?('Diagnostic-Code:')
|
144
|
+
next unless cv = e.match(/\A[ \t]+(.+)\z/)
|
145
|
+
v['diagnosis'] << ' ' << cv[1]
|
146
|
+
havepassed[-1] = 'Diagnostic-Code: ' << e
|
164
147
|
end
|
165
148
|
end
|
166
|
-
end
|
149
|
+
end # End of message/delivery-status
|
167
150
|
end
|
168
151
|
return nil unless recipients > 0
|
169
152
|
|
170
153
|
dscontents.each do |e|
|
171
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
172
|
-
|
173
154
|
# Get the value of SMTP status code as a pseudo D.S.N.
|
155
|
+
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
174
156
|
if cv = e['diagnosis'].match(/\b([45])\d\d[ \t]*/)
|
175
157
|
# 4xx or 5xx
|
176
158
|
e['status'] = cv[1] + '.0.0'
|
@@ -179,8 +161,7 @@ module Sisimai::Bite::Email
|
|
179
161
|
if e['status'] == '5.0.0' || e['status'] == '4.0.0'
|
180
162
|
# Get the value of D.S.N. from the error message or the value of
|
181
163
|
# Diagnostic-Code header.
|
182
|
-
|
183
|
-
e['status'] = pseudostatus unless pseudostatus.empty?
|
164
|
+
e['status'] = Sisimai::SMTP::Status.find(e['diagnosis']) || ''
|
184
165
|
end
|
185
166
|
|
186
167
|
if e['action'] == 'expired'
|
@@ -189,11 +170,11 @@ module Sisimai::Bite::Email
|
|
189
170
|
if !e['status'] || e['status'].end_with?('.0.0')
|
190
171
|
# Set pseudo Status code value if the value of Status is not
|
191
172
|
# defined or 4.0.0 or 5.0.0.
|
192
|
-
|
193
|
-
e['status'] = pseudostatus unless pseudostatus.empty?
|
173
|
+
e['status'] = Sisimai::SMTP::Status.code('expired') || e['status']
|
194
174
|
end
|
195
175
|
end
|
196
176
|
|
177
|
+
e['lhost'] ||= permessage['rhost']
|
197
178
|
e['agent'] = self.smtpagent
|
198
179
|
e['command'] = commandtxt
|
199
180
|
end
|
@@ -12,7 +12,10 @@ module Sisimai::Bite::Email
|
|
12
12
|
# savemail.c:1040|if (printheader && !putline(" ----- Transcript of session follows -----\n",
|
13
13
|
# savemail.c:1041| mci))
|
14
14
|
# savemail.c:1042| goto writeerr;
|
15
|
-
#
|
15
|
+
# savemail.c:1360|if (!putline(
|
16
|
+
# savemail.c:1361| sendbody
|
17
|
+
# savemail.c:1362| ? " ----- Original message follows -----\n"
|
18
|
+
# savemail.c:1363| : " ----- Message header follows -----\n",
|
16
19
|
rfc822: ['Content-Type: message/rfc822', 'Content-Type: text/rfc822-headers'],
|
17
20
|
message: [' ----- Transcript of session follows -----'],
|
18
21
|
error: ['... while talking to '],
|
@@ -41,6 +44,10 @@ module Sisimai::Bite::Email
|
|
41
44
|
return nil unless mhead['from'].start_with?('Mail Delivery Subsystem')
|
42
45
|
end
|
43
46
|
|
47
|
+
require 'sisimai/rfc1894'
|
48
|
+
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
49
|
+
permessage = {} # (Hash) Store values of each Per-Message field
|
50
|
+
|
44
51
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
45
52
|
hasdivided = mbody.split("\n")
|
46
53
|
havepassed = ['']
|
@@ -51,11 +58,6 @@ module Sisimai::Bite::Email
|
|
51
58
|
commandtxt = '' # (String) SMTP Command name begin with the string '>>>'
|
52
59
|
esmtpreply = '' # (String) Reply from remote server on SMTP session
|
53
60
|
sessionerr = false # (Boolean) Flag, "true" if it is SMTP session error
|
54
|
-
connvalues = 0 # (Integer) Flag, 1 if all the value of connheader have been set
|
55
|
-
connheader = {
|
56
|
-
'date' => '', # The value of Arrival-Date header
|
57
|
-
'rhost' => '', # The value of Reporting-MTA header
|
58
|
-
}
|
59
61
|
anotherset = {} # Another error information
|
60
62
|
v = nil
|
61
63
|
|
@@ -65,7 +67,7 @@ module Sisimai::Bite::Email
|
|
65
67
|
p = havepassed[-2]
|
66
68
|
|
67
69
|
if readcursor == 0
|
68
|
-
# Beginning of the bounce message or delivery
|
70
|
+
# Beginning of the bounce message or message/delivery-status part
|
69
71
|
if e.start_with?(StartingOf[:message][0])
|
70
72
|
readcursor |= Indicators[:deliverystatus]
|
71
73
|
next
|
@@ -73,7 +75,7 @@ module Sisimai::Bite::Email
|
|
73
75
|
end
|
74
76
|
|
75
77
|
if (readcursor & Indicators[:'message-rfc822']) == 0
|
76
|
-
# Beginning of the original message part
|
78
|
+
# Beginning of the original message part(message/rfc822)
|
77
79
|
if e.start_with?(StartingOf[:rfc822][0], StartingOf[:rfc822][1])
|
78
80
|
readcursor |= Indicators[:'message-rfc822']
|
79
81
|
next
|
@@ -81,7 +83,7 @@ module Sisimai::Bite::Email
|
|
81
83
|
end
|
82
84
|
|
83
85
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
84
|
-
#
|
86
|
+
# message/rfc822 OR text/rfc822-headers part
|
85
87
|
if e.empty?
|
86
88
|
blanklines += 1
|
87
89
|
break if blanklines > 1
|
@@ -89,65 +91,46 @@ module Sisimai::Bite::Email
|
|
89
91
|
end
|
90
92
|
rfc822list << e
|
91
93
|
else
|
92
|
-
#
|
94
|
+
# message/delivery-status part
|
93
95
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
94
96
|
next if e.empty?
|
95
97
|
|
96
|
-
if
|
97
|
-
#
|
98
|
-
|
99
|
-
# Action: failed
|
100
|
-
# Status: 5.1.1
|
101
|
-
# Remote-MTA: DNS; mx.example.jp
|
102
|
-
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
103
|
-
# Last-Attempt-Date: Fri, 14 Feb 2014 12:30:08 -0500
|
98
|
+
if f = Sisimai::RFC1894.match(e)
|
99
|
+
# "e" matched with any field defined in RFC3464
|
100
|
+
o = Sisimai::RFC1894.field(e) || next
|
104
101
|
v = dscontents[-1]
|
105
102
|
|
106
|
-
if
|
107
|
-
# Final-Recipient:
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
v
|
103
|
+
if o[-1] == 'addr'
|
104
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
105
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
106
|
+
if o[0] == 'final-recipient'
|
107
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
108
|
+
if v['recipient']
|
109
|
+
# There are multiple recipient addresses in the message body.
|
110
|
+
dscontents << Sisimai::Bite.DELIVERYSTATUS
|
111
|
+
v = dscontents[-1]
|
112
|
+
end
|
113
|
+
v['recipient'] = o[2]
|
114
|
+
recipients += 1
|
115
|
+
else
|
116
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
117
|
+
v['alias'] = o[2]
|
112
118
|
end
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
# X-Actual-Recipient: RFC822; kijitora@example.co.jp
|
118
|
-
v['alias'] = cv[1]
|
119
|
-
|
120
|
-
elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
|
121
|
-
# Action: failed
|
122
|
-
v['action'] = cv[1].downcase
|
123
|
-
|
124
|
-
elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
|
125
|
-
# Status: 5.1.1
|
126
|
-
# Status:5.2.0
|
127
|
-
# Status: 5.1.0 (permanent failure)
|
128
|
-
v['status'] = cv[1]
|
129
|
-
|
130
|
-
elsif cv = e.match(/\ARemote-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
131
|
-
# Remote-MTA: DNS; mx.example.jp
|
132
|
-
v['rhost'] = cv[1].downcase
|
133
|
-
v['rhost'] = '' if v['rhost'] =~ /\A\s+\z/ # Remote-MTA: DNS;
|
134
|
-
|
135
|
-
elsif cv = e.match(/\ALast-Attempt-Date:[ ]*(.+)\z/)
|
136
|
-
# Last-Attempt-Date: Fri, 14 Feb 2014 12:30:08 -0500
|
137
|
-
v['date'] = cv[1]
|
119
|
+
elsif o[-1] == 'code'
|
120
|
+
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
121
|
+
v['spec'] = o[1]
|
122
|
+
v['diagnosis'] = o[2]
|
138
123
|
else
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
v['diagnosis'] = cv[2]
|
124
|
+
# Other DSN fields defined in RFC3464
|
125
|
+
next unless fieldtable.key?(o[0])
|
126
|
+
v[fieldtable[o[0]]] = o[2]
|
143
127
|
|
144
|
-
|
145
|
-
|
146
|
-
v['diagnosis'] << ' ' << cv[1]
|
147
|
-
havepassed[-1] = 'Diagnostic-Code: ' << e
|
148
|
-
end
|
128
|
+
next unless f == 1
|
129
|
+
permessage[fieldtable[o[0]]] = o[2]
|
149
130
|
end
|
150
131
|
else
|
132
|
+
# The line does not begin with a DSN field defined in RFC3464
|
133
|
+
#
|
151
134
|
# ----- Transcript of session follows -----
|
152
135
|
# ... while talking to mta.example.org.:
|
153
136
|
# >>> DATA
|
@@ -157,77 +140,66 @@ module Sisimai::Bite::Email
|
|
157
140
|
# Reporting-MTA: dns; mx.example.jp
|
158
141
|
# Received-From-MTA: DNS; x1x2x3x4.dhcp.example.ne.jp
|
159
142
|
# Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
elsif cv = e.match(/\AReporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
169
|
-
# Reporting-MTA: dns; mx.example.jp
|
170
|
-
next unless connheader['rhost'].empty?
|
171
|
-
connheader['rhost'] = cv[1].downcase
|
172
|
-
connvalues += 1
|
173
|
-
|
174
|
-
elsif cv = e.match(/\AReceived-From-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
175
|
-
# Received-From-MTA: DNS; x1x2x3x4.dhcp.example.ne.jp
|
176
|
-
next if connheader['lhost']
|
177
|
-
|
178
|
-
# The value of "lhost" is optional
|
179
|
-
connheader['lhost'] = cv[1].downcase
|
180
|
-
connvalues += 1
|
181
|
-
|
182
|
-
elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/)
|
183
|
-
# Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
|
184
|
-
next unless connheader['date'].empty?
|
185
|
-
connheader['date'] = cv[1]
|
186
|
-
connvalues += 1
|
187
|
-
else
|
188
|
-
# Detect SMTP session error or connection error
|
189
|
-
next if sessionerr
|
190
|
-
if e.start_with?(StartingOf[:error][0])
|
191
|
-
# ----- Transcript of session follows -----
|
192
|
-
# ... while talking to mta.example.org.:
|
193
|
-
sessionerr = true
|
194
|
-
next
|
195
|
-
end
|
196
|
-
|
197
|
-
if cv = e.match(/\A[<](.+)[>][.]+ (.+)\z/)
|
198
|
-
# <kijitora@example.co.jp>... Deferred: Name server: example.co.jp.: host name lookup failure
|
199
|
-
anotherset['recipient'] = cv[1]
|
200
|
-
anotherset['diagnosis'] = cv[2]
|
143
|
+
unless e.start_with?(' ')
|
144
|
+
if cv = e.match(/\A[>]{3}[ ]+([A-Z]{4})[ ]?/)
|
145
|
+
# >>> DATA
|
146
|
+
commandtxt = cv[1]
|
147
|
+
|
148
|
+
elsif cv = e.match(/\A[<]{3}[ ]+(.+)\z/)
|
149
|
+
# <<< Response
|
150
|
+
esmtpreply = cv[1]
|
201
151
|
else
|
202
|
-
#
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
# 554 5.3.0 unknown mailer error 255
|
211
|
-
anotherset['status'] = cv[1]
|
212
|
-
anotherset['diagnosis'] ||= ''
|
213
|
-
anotherset['diagnosis'] << ' ' << e
|
152
|
+
# Detect SMTP session error or connection error
|
153
|
+
next if sessionerr
|
154
|
+
if e.start_with?(StartingOf[:error][0])
|
155
|
+
# ----- Transcript of session follows -----
|
156
|
+
# ... while talking to mta.example.org.:
|
157
|
+
sessionerr = true
|
158
|
+
next
|
159
|
+
end
|
214
160
|
|
215
|
-
|
161
|
+
if cv = e.match(/\A[<](.+)[>][.]+ (.+)\z/)
|
162
|
+
# <kijitora@example.co.jp>... Deferred: Name server: example.co.jp.: host name lookup failure
|
163
|
+
anotherset['recipient'] = cv[1]
|
164
|
+
anotherset['diagnosis'] = cv[2]
|
165
|
+
else
|
166
|
+
# ----- Transcript of session follows -----
|
216
167
|
# Message could not be delivered for too long
|
217
|
-
#
|
218
|
-
|
219
|
-
|
168
|
+
# Message will be deleted from queue
|
169
|
+
next if e =~ /\A[ \t]*[-]+/
|
170
|
+
if cv = e.match(/\A[45]\d\d[ \t]([45][.]\d[.]\d)[ \t].+/)
|
171
|
+
# 550 5.1.2 <kijitora@example.org>... Message
|
172
|
+
#
|
173
|
+
# DBI connect('dbname=...')
|
174
|
+
# 554 5.3.0 unknown mailer error 255
|
175
|
+
anotherset['status'] = cv[1]
|
176
|
+
anotherset['diagnosis'] ||= ''
|
177
|
+
anotherset['diagnosis'] << ' ' << e
|
178
|
+
|
179
|
+
elsif e.start_with?('Message ', 'Warning: ')
|
180
|
+
# Message could not be delivered for too long
|
181
|
+
# Warning: message still undelivered after 4 hours
|
182
|
+
anotherset['diagnosis'] ||= ''
|
183
|
+
anotherset['diagnosis'] << ' ' << e
|
184
|
+
end
|
220
185
|
end
|
221
186
|
end
|
187
|
+
else
|
188
|
+
# Continued line of the value of Diagnostic-Code field
|
189
|
+
next unless p.start_with?('Diagnostic-Code:')
|
190
|
+
next unless cv = e.match(/\A[ \t]+(.+)\z/)
|
191
|
+
v['diagnosis'] << ' ' << cv[1]
|
192
|
+
havepassed[-1] = 'Diagnostic-Code: ' << e
|
222
193
|
end
|
223
194
|
end
|
224
|
-
end
|
195
|
+
end # End of message/delivery-status
|
225
196
|
end
|
226
197
|
return nil unless recipients > 0
|
227
198
|
|
228
199
|
dscontents.each do |e|
|
229
200
|
# Set default values if each value is empty.
|
230
|
-
|
201
|
+
e['lhost'] ||= permessage['rhost']
|
202
|
+
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
231
203
|
|
232
204
|
e['agent'] = self.smtpagent
|
233
205
|
e['command'] ||= commandtxt
|