sisimai 5.0.3 → 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.
- checksums.yaml +4 -4
- data/.github/workflows/codecovio.yml +3 -1
- data/.github/workflows/rake-test.yml +7 -3
- data/ChangeLog.md +136 -0
- data/Makefile +4 -2
- data/README-JA.md +32 -22
- data/README.md +31 -21
- data/lib/sisimai/arf.rb +124 -213
- data/lib/sisimai/fact/json.rb +2 -2
- data/lib/sisimai/fact/yaml.rb +2 -2
- data/lib/sisimai/fact.rb +208 -173
- data/lib/sisimai/lda.rb +98 -0
- data/lib/sisimai/lhost/activehunter.rb +5 -4
- data/lib/sisimai/lhost/amazonses.rb +189 -305
- data/lib/sisimai/lhost/apachejames.rb +52 -55
- data/lib/sisimai/lhost/biglobe.rb +5 -6
- data/lib/sisimai/lhost/courier.rb +14 -12
- data/lib/sisimai/lhost/domino.rb +29 -29
- data/lib/sisimai/lhost/dragonfly.rb +113 -0
- data/lib/sisimai/lhost/einsundeins.rb +7 -8
- data/lib/sisimai/lhost/exchange2003.rb +10 -11
- data/lib/sisimai/lhost/exchange2007.rb +115 -104
- data/lib/sisimai/lhost/exim.rb +236 -246
- data/lib/sisimai/lhost/ezweb.rb +47 -55
- data/lib/sisimai/lhost/fml.rb +6 -7
- data/lib/sisimai/lhost/gmail.rb +36 -32
- data/lib/sisimai/lhost/gmx.rb +8 -20
- data/lib/sisimai/lhost/googlegroups.rb +13 -12
- data/lib/sisimai/lhost/googleworkspace.rb +94 -0
- data/lib/sisimai/lhost/imailserver.rb +11 -19
- data/lib/sisimai/lhost/interscanmss.rb +6 -5
- data/lib/sisimai/lhost/kddi.rb +7 -8
- data/lib/sisimai/lhost/mailfoundry.rb +6 -9
- data/lib/sisimai/lhost/mailmarshalsmtp.rb +6 -6
- data/lib/sisimai/lhost/messagingserver.rb +19 -17
- data/lib/sisimai/lhost/mfilter.rb +8 -7
- data/lib/sisimai/lhost/notes.rb +6 -8
- data/lib/sisimai/lhost/opensmtpd.rb +11 -9
- data/lib/sisimai/lhost/postfix.rb +29 -31
- data/lib/sisimai/lhost/qmail.rb +136 -112
- data/lib/sisimai/lhost/sendmail.rb +23 -22
- data/lib/sisimai/lhost/v5sendmail.rb +93 -64
- data/lib/sisimai/lhost/verizon.rb +6 -6
- data/lib/sisimai/lhost/x1.rb +4 -4
- data/lib/sisimai/lhost/x2.rb +4 -5
- data/lib/sisimai/lhost/x3.rb +5 -5
- data/lib/sisimai/lhost/x6.rb +4 -4
- data/lib/sisimai/lhost/zoho.rb +6 -6
- data/lib/sisimai/lhost.rb +21 -24
- data/lib/sisimai/mail/maildir.rb +1 -1
- data/lib/sisimai/mail/stdin.rb +1 -1
- data/lib/sisimai/message.rb +100 -153
- data/lib/sisimai/order.rb +22 -77
- data/lib/sisimai/reason/authfailure.rb +1 -4
- data/lib/sisimai/reason/badreputation.rb +3 -3
- data/lib/sisimai/reason/blocked.rb +7 -10
- data/lib/sisimai/reason/contenterror.rb +7 -1
- data/lib/sisimai/reason/exceedlimit.rb +1 -4
- data/lib/sisimai/reason/failedstarttls.rb +42 -0
- data/lib/sisimai/reason/filtered.rb +5 -4
- data/lib/sisimai/reason/hasmoved.rb +1 -2
- data/lib/sisimai/reason/hostunknown.rb +3 -3
- data/lib/sisimai/reason/mailboxfull.rb +2 -4
- data/lib/sisimai/reason/mailererror.rb +1 -2
- data/lib/sisimai/reason/mesgtoobig.rb +2 -4
- data/lib/sisimai/reason/norelaying.rb +3 -3
- data/lib/sisimai/reason/notaccept.rb +2 -3
- data/lib/sisimai/reason/notcompliantrfc.rb +10 -4
- data/lib/sisimai/reason/rejected.rb +2 -1
- data/lib/sisimai/reason/requireptr.rb +2 -2
- data/lib/sisimai/reason/securityerror.rb +1 -3
- data/lib/sisimai/reason/spamdetected.rb +6 -8
- data/lib/sisimai/reason/speeding.rb +1 -2
- data/lib/sisimai/reason/suppressed.rb +36 -0
- data/lib/sisimai/reason/suspend.rb +1 -3
- data/lib/sisimai/reason/systemerror.rb +5 -0
- data/lib/sisimai/reason/toomanyconn.rb +1 -2
- data/lib/sisimai/reason/userunknown.rb +1 -1
- data/lib/sisimai/reason/virusdetected.rb +5 -6
- data/lib/sisimai/reason.rb +82 -78
- data/lib/sisimai/rfc1123.rb +152 -0
- data/lib/sisimai/rfc1894.rb +102 -62
- data/lib/sisimai/rfc2045.rb +2 -1
- data/lib/sisimai/rfc3464/thirdparty.rb +102 -0
- data/lib/sisimai/rfc3464.rb +224 -345
- data/lib/sisimai/rfc3834.rb +3 -3
- data/lib/sisimai/rfc5322.rb +7 -17
- data/lib/sisimai/rfc791.rb +69 -0
- data/lib/sisimai/rhost/aol.rb +36 -0
- data/lib/sisimai/rhost/apple.rb +95 -0
- data/lib/sisimai/rhost/cox.rb +84 -34
- data/lib/sisimai/rhost/facebook.rb +100 -0
- data/lib/sisimai/rhost/franceptt.rb +87 -83
- data/lib/sisimai/rhost/godaddy.rb +208 -45
- data/lib/sisimai/rhost/google.rb +22 -22
- data/lib/sisimai/rhost/gsuite.rb +42 -0
- data/lib/sisimai/rhost/iua.rb +5 -5
- data/lib/sisimai/rhost/kddi.rb +9 -7
- data/lib/sisimai/rhost/messagelabs.rb +37 -0
- data/lib/sisimai/rhost/microsoft.rb +60 -54
- data/lib/sisimai/rhost/mimecast.rb +44 -31
- data/lib/sisimai/rhost/nttdocomo.rb +5 -4
- data/lib/sisimai/rhost/outlook.rb +36 -0
- data/lib/sisimai/rhost/spectrum.rb +102 -41
- data/lib/sisimai/rhost/tencent.rb +48 -26
- data/lib/sisimai/rhost/yahooinc.rb +111 -0
- data/lib/sisimai/rhost.rb +65 -42
- data/lib/sisimai/smtp/command.rb +31 -21
- data/lib/sisimai/smtp/failure.rb +103 -0
- data/lib/sisimai/smtp/reply.rb +29 -24
- data/lib/sisimai/smtp/status.rb +36 -19
- data/lib/sisimai/smtp/transcript.rb +18 -18
- data/lib/sisimai/string.rb +0 -46
- data/lib/sisimai/version.rb +1 -1
- data/lib/sisimai.rb +0 -6
- data/set-of-emails/maildir/bsd/lhost-dragonfly-01.eml +36 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-02.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-03.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-04.eml +31 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-05.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-06.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-07.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-08.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-09.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-10.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-11.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-12.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-13.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-14.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-15.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-16.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-17.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-18.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-19.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-20.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-21.eml +33 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-22.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-23.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-24.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-25.eml +33 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-26.eml +33 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-27.eml +47 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-28.eml +47 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-29.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-dragonfly-30.eml +32 -0
- data/set-of-emails/maildir/bsd/lhost-opensmtpd-10.eml +58 -0
- data/set-of-emails/maildir/bsd/lhost-opensmtpd-11.eml +58 -0
- data/set-of-emails/maildir/bsd/lhost-opensmtpd-12.eml +62 -0
- data/set-of-emails/maildir/bsd/lhost-opensmtpd-13.eml +62 -0
- data/set-of-emails/maildir/bsd/lhost-opensmtpd-14.eml +58 -0
- data/set-of-emails/maildir/bsd/lhost-opensmtpd-15.eml +63 -0
- data/set-of-emails/maildir/bsd/lhost-opensmtpd-16.eml +62 -0
- data/set-of-emails/maildir/bsd/lhost-opensmtpd-17.eml +63 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-30.eml +81 -81
- data/set-of-emails/maildir/bsd/lhost-qmail-11.eml +29 -0
- data/set-of-emails/maildir/bsd/lhost-qmail-12.eml +29 -0
- data/set-of-emails/maildir/bsd/lhost-qmail-13.eml +29 -0
- data/set-of-emails/maildir/bsd/lhost-qmail-14.eml +34 -0
- data/set-of-emails/maildir/bsd/lhost-qmail-15.eml +30 -0
- data/set-of-emails/maildir/bsd/lhost-qmail-16.eml +31 -0
- data/set-of-emails/maildir/bsd/lhost-qmail-17.eml +38 -0
- data/set-of-emails/maildir/bsd/lhost-qmail-18.eml +31 -0
- data/set-of-emails/maildir/bsd/lhost-qmail-19.eml +31 -0
- data/set-of-emails/maildir/bsd/lhost-qmail-20.eml +46 -0
- data/set-of-emails/maildir/bsd/lhost-qmail-21.eml +41 -0
- data/set-of-emails/maildir/bsd/lhost-qmail-22.eml +42 -0
- data/set-of-emails/maildir/bsd/lhost-qmail-23.eml +43 -0
- data/set-of-emails/maildir/bsd/lhost-qmail-24.eml +43 -0
- data/set-of-emails/maildir/bsd/lhost-qmail-25.eml +54 -0
- data/set-of-emails/maildir/bsd/{lhost-aol-03.eml → rhost-aol-03.eml} +1264 -1264
- data/set-of-emails/maildir/bsd/{lhost-aol-04.eml → rhost-aol-04.eml} +1260 -1260
- data/set-of-emails/maildir/bsd/{lhost-aol-05.eml → rhost-aol-05.eml} +105 -105
- data/set-of-emails/maildir/bsd/{lhost-aol-06.eml → rhost-aol-06.eml} +105 -105
- data/set-of-emails/maildir/bsd/rhost-apple-01.eml +79 -0
- data/set-of-emails/maildir/bsd/rhost-apple-02.eml +81 -0
- data/set-of-emails/maildir/bsd/rhost-apple-03.eml +75 -0
- data/set-of-emails/maildir/bsd/rhost-apple-04.eml +74 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-01.eml +189 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-02.eml +180 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-03.eml +251 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-04.eml +211 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-05.eml +226 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-06.eml +257 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-07.eml +289 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-08.eml +231 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-09.eml +231 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-10.eml +254 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-11.eml +228 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-12.eml +271 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-13.eml +261 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-14.eml +273 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-15.eml +229 -0
- data/set-of-emails/maildir/bsd/{lhost-messagelabs-01.eml → rhost-messagelabs-01.eml} +93 -93
- data/set-of-emails/maildir/bsd/rhost-outlook-01.eml +72 -0
- data/set-of-emails/maildir/bsd/rhost-outlook-02.eml +72 -0
- data/set-of-emails/maildir/bsd/rhost-outlook-03.eml +72 -0
- data/set-of-emails/maildir/bsd/rhost-outlook-04.eml +79 -0
- data/set-of-emails/maildir/bsd/rhost-outlook-06.eml +75 -0
- data/set-of-emails/maildir/bsd/rhost-outlook-07.eml +70 -0
- data/set-of-emails/maildir/bsd/rhost-outlook-08.eml +70 -0
- data/set-of-emails/maildir/bsd/rhost-outlook-09.eml +56 -0
- data/set-of-emails/maildir/bsd/rhost-yahooinc-01.eml +80 -0
- data/set-of-emails/maildir/bsd/rhost-yahooinc-02.eml +83 -0
- data/set-of-emails/maildir/bsd/rhost-yahooinc-03.eml +125 -0
- data/set-of-emails/maildir/tmp/arf-22.eml +49 -0
- data/set-of-emails/maildir/tmp/arf-23.eml +49 -0
- data/set-of-emails/maildir/tmp/arf-24.eml +50 -0
- data/set-of-emails/maildir/tmp/lhost-exim-07.eml +28 -0
- metadata +136 -56
- data/lib/sisimai/lhost/amavis.rb +0 -163
- data/lib/sisimai/lhost/amazonworkmail.rb +0 -127
- data/lib/sisimai/lhost/aol.rb +0 -125
- data/lib/sisimai/lhost/barracuda.rb +0 -92
- data/lib/sisimai/lhost/bigfoot.rb +0 -125
- data/lib/sisimai/lhost/facebook.rb +0 -188
- data/lib/sisimai/lhost/gsuite.rb +0 -194
- data/lib/sisimai/lhost/mailru.rb +0 -214
- data/lib/sisimai/lhost/mcafee.rb +0 -109
- data/lib/sisimai/lhost/messagelabs.rb +0 -119
- data/lib/sisimai/lhost/mxlogic.rb +0 -198
- data/lib/sisimai/lhost/office365.rb +0 -252
- data/lib/sisimai/lhost/outlook.rb +0 -129
- data/lib/sisimai/lhost/powermta.rb +0 -118
- data/lib/sisimai/lhost/receivingses.rb +0 -126
- data/lib/sisimai/lhost/sendgrid.rb +0 -150
- data/lib/sisimai/lhost/surfcontrol.rb +0 -105
- data/lib/sisimai/lhost/x4.rb +0 -269
- data/lib/sisimai/lhost/x5.rb +0 -112
- data/lib/sisimai/lhost/yahoo.rb +0 -102
- data/lib/sisimai/lhost/yandex.rb +0 -118
- data/lib/sisimai/mda.rb +0 -121
- data/lib/sisimai/smtp/error.rb +0 -119
- /data/set-of-emails/maildir/bsd/{lhost-googlegroups-15.eml → lhost-googleworkspace-01.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-x4-08.eml → lhost-x2-06.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-01.eml → rfc3464-51.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-03.eml → rfc3464-52.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-04.eml → rfc3464-53.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-05.eml → rfc3464-54.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-06.eml → rfc3464-55.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-07.eml → rfc3464-56.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-08.eml → rfc3464-57.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-09.eml → rfc3464-58.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-10.eml → rfc3464-59.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-11.eml → rfc3464-60.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-12.eml → rfc3464-61.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-13.eml → rfc3464-62.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-14.eml → rfc3464-63.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-15.eml → rfc3464-64.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-02.eml → rfc3464-65.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-aol-01.eml → rhost-aol-01.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-aol-02.eml → rhost-aol-02.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-facebook-03.eml → rhost-facebook-03.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-facebook-04.eml → rhost-facebook-04.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-messagelabs-02.eml → rhost-messagelabs-02.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-messagelabs-03.eml → rhost-messagelabs-03.eml} +0 -0
- /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-37.eml +0 -0
- /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-38.eml +0 -0
- /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-39.eml +0 -0
data/lib/sisimai/lhost/x4.rb
DELETED
@@ -1,269 +0,0 @@
|
|
1
|
-
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::X4 parses a bounce email which created by some qmail clone. Methods in the module
|
3
|
-
# are called from only Sisimai::Message.
|
4
|
-
module X4
|
5
|
-
class << self
|
6
|
-
# MTA module for qmail clones
|
7
|
-
require 'sisimai/lhost'
|
8
|
-
|
9
|
-
Indicators = Sisimai::Lhost.INDICATORS
|
10
|
-
Boundaries = ['--- Below this line is a copy of the message.', 'Original message follows.'].freeze
|
11
|
-
StartingOf = {
|
12
|
-
# qmail-remote.c:248| if (code >= 500) {
|
13
|
-
# qmail-remote.c:249| out("h"); outhost(); out(" does not like recipient.\n");
|
14
|
-
# qmail-remote.c:265| if (code >= 500) quit("D"," failed on DATA command");
|
15
|
-
# qmail-remote.c:271| if (code >= 500) quit("D"," failed after I sent the message");
|
16
|
-
#
|
17
|
-
# Characters: K,Z,D in qmail-qmqpc.c, qmail-send.c, qmail-rspawn.c
|
18
|
-
# K = success, Z = temporary error, D = permanent error
|
19
|
-
error: ['Remote host said:'],
|
20
|
-
message: [
|
21
|
-
'He/Her is not ',
|
22
|
-
'unable to deliver your message to the following addresses',
|
23
|
-
'Su mensaje no pudo ser entregado',
|
24
|
-
'This is the machine generated message from mail service',
|
25
|
-
'This is the mail delivery agent at',
|
26
|
-
'Unable to deliver message to the following address',
|
27
|
-
'Unfortunately, your mail was not delivered to the following address:',
|
28
|
-
'Your mail message to the following address',
|
29
|
-
'Your message to the following addresses',
|
30
|
-
"We're sorry.",
|
31
|
-
],
|
32
|
-
rhost: ['Giving up on ', 'Connected to ', 'remote host '],
|
33
|
-
}.freeze
|
34
|
-
CommandSet = {
|
35
|
-
# Error text regular expressions which defined in qmail-remote.c
|
36
|
-
# qmail-remote.c:225| if (smtpcode() != 220) quit("ZConnected to "," but greeting failed");
|
37
|
-
'conn' => [' but greeting failed.'],
|
38
|
-
# qmail-remote.c:231| if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
|
39
|
-
'ehlo' => [' but my name was rejected.'],
|
40
|
-
# qmail-remote.c:238| if (code >= 500) quit("DConnected to "," but sender was rejected");
|
41
|
-
# reason = rejected
|
42
|
-
'mail' => [' but sender was rejected.'],
|
43
|
-
# qmail-remote.c:249| out("h"); outhost(); out(" does not like recipient.\n");
|
44
|
-
# qmail-remote.c:253| out("s"); outhost(); out(" does not like recipient.\n");
|
45
|
-
# reason = userunknown
|
46
|
-
'rcpt' => [' does not like recipient.'],
|
47
|
-
# qmail-remote.c:265| if (code >= 500) quit("D"," failed on DATA command");
|
48
|
-
# qmail-remote.c:266| if (code >= 400) quit("Z"," failed on DATA command");
|
49
|
-
# qmail-remote.c:271| if (code >= 500) quit("D"," failed after I sent the message");
|
50
|
-
# qmail-remote.c:272| if (code >= 400) quit("Z"," failed after I sent the message");
|
51
|
-
'data' => [' failed on DATA command', ' failed after I sent the message'],
|
52
|
-
}.freeze
|
53
|
-
|
54
|
-
ReSMTP = {
|
55
|
-
# Error text regular expressions which defined in qmail-remote.c
|
56
|
-
# qmail-remote.c:225| if (smtpcode() != 220) quit("ZConnected to "," but greeting failed");
|
57
|
-
'conn' => %r/(?:Error:)?Connected to [^ ]+ but greeting failed[.]/,
|
58
|
-
# qmail-remote.c:231| if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
|
59
|
-
'ehlo' => %r/(?:Error:)?Connected to [^ ]+ but my name was rejected[.]/,
|
60
|
-
# qmail-remote.c:238| if (code >= 500) quit("DConnected to "," but sender was rejected");
|
61
|
-
# reason = rejected
|
62
|
-
'mail' => %r/(?:Error:)?Connected to [^ ]+ but sender was rejected[.]/,
|
63
|
-
# qmail-remote.c:249| out("h"); outhost(); out(" does not like recipient.\n");
|
64
|
-
# qmail-remote.c:253| out("s"); outhost(); out(" does not like recipient.\n");
|
65
|
-
# reason = userunknown
|
66
|
-
'rcpt' => %r/(?:Error:)?[^ ]+ does not like recipient[.]/,
|
67
|
-
# qmail-remote.c:265| if (code >= 500) quit("D"," failed on DATA command");
|
68
|
-
# qmail-remote.c:266| if (code >= 400) quit("Z"," failed on DATA command");
|
69
|
-
# qmail-remote.c:271| if (code >= 500) quit("D"," failed after I sent the message");
|
70
|
-
# qmail-remote.c:272| if (code >= 400) quit("Z"," failed after I sent the message");
|
71
|
-
'data' => %r{(?:
|
72
|
-
(?:Error:)?[^ ]+[ ]failed[ ]on[ ]DATA[ ]command[.]
|
73
|
-
|(?:Error:)?[^ ]+[ ]failed[ ]after[ ]I[ ]sent[ ]the[ ]message[.]
|
74
|
-
)
|
75
|
-
}x,
|
76
|
-
}.freeze
|
77
|
-
|
78
|
-
# qmail-send.c:922| ... (&dline[c],"I'm not going to try again; this message has been in the queue too long.\n")) nomem();
|
79
|
-
HasExpired = 'this message has been in the queue too long.'
|
80
|
-
OnHoldPair = [' does not like recipient.', 'this message has been in the queue too long.'].freeze
|
81
|
-
FailOnLDAP = {
|
82
|
-
# qmail-ldap-1.03-20040101.patch:19817 - 19866
|
83
|
-
'suspend' => ['Mailaddress is administrative?le?y disabled'], # 5.2.1
|
84
|
-
'userunknown' => ['Sorry, no mailbox here by that name'], # 5.1.1
|
85
|
-
'exceedlimit' => ['The message exeeded the maximum size the user accepts'], # 5.2.3
|
86
|
-
'systemerror' => [
|
87
|
-
'Automatic homedir creator crashed', # 4.3.0
|
88
|
-
'Illegal value in LDAP attribute', # 5.3.5
|
89
|
-
'LDAP attribute is not given but mandatory', # 5.3.5
|
90
|
-
'Timeout while performing search on LDAP server', # 4.4.3
|
91
|
-
'Too many results returned but needs to be unique', # 5.3.5
|
92
|
-
'Permanent error while executing qmail-forward', # 5.4.4
|
93
|
-
'Temporary error in automatic homedir creation', # 4.3.0 or 5.3.0
|
94
|
-
'Temporary error while executing qmail-forward', # 4.4.4
|
95
|
-
'Temporary failure in LDAP lookup', # 4.4.3
|
96
|
-
'Unable to contact LDAP server', # 4.4.3
|
97
|
-
'Unable to login into LDAP server, bad credentials',# 4.4.3
|
98
|
-
],
|
99
|
-
}.freeze
|
100
|
-
MessagesOf = {
|
101
|
-
# qmail-local.c:589| strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)");
|
102
|
-
# qmail-remote.c:253| out("s"); outhost(); out(" does not like recipient.\n");
|
103
|
-
'userunknown' => ['no mailbox here by that name', 'does not like recipient.'],
|
104
|
-
# error_str.c:192| X(EDQUOT,"disk quota exceeded")
|
105
|
-
'mailboxfull' => ['disk quota exceeded'],
|
106
|
-
# qmail-qmtpd.c:233| ... result = "Dsorry, that message size exceeds my databytes limit (#5.3.4)";
|
107
|
-
# qmail-smtpd.c:391| ... out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return;
|
108
|
-
'mesgtoobig' => ['Message size exceeds fixed maximum message size:'],
|
109
|
-
# qmail-remote.c:68| Sorry, I couldn't find any host by that name. (#4.1.2)\n"); zerodie();
|
110
|
-
# qmail-remote.c:78| Sorry, I couldn't find any host named ");
|
111
|
-
'hostunknown' => ["Sorry, I couldn't find any host "],
|
112
|
-
'systemfull' => ['Requested action not taken: mailbox unavailable (not enough free space)'],
|
113
|
-
'systemerror' => [
|
114
|
-
'bad interpreter: No such file or directory',
|
115
|
-
'system error',
|
116
|
-
'Unable to',
|
117
|
-
],
|
118
|
-
'networkerror' => [
|
119
|
-
"Sorry, I wasn't able to establish an SMTP connection",
|
120
|
-
"Sorry, I couldn't find a mail exchanger or IP address",
|
121
|
-
"Sorry. Although I'm listed as a best-preference MX or A for that host",
|
122
|
-
],
|
123
|
-
}.freeze
|
124
|
-
|
125
|
-
# Parse bounce messages from Unknown MTA #4
|
126
|
-
# @param [Hash] mhead Message headers of a bounce email
|
127
|
-
# @param [String] mbody Message body of a bounce email
|
128
|
-
# @return [Hash] Bounce data list and message/rfc822 part
|
129
|
-
# @return [Nil] it failed to parse or the arguments are missing
|
130
|
-
def inquire(mhead, mbody)
|
131
|
-
# Pre process email headers and the body part of the message which generated by qmail, see
|
132
|
-
# https://cr.yp.to/qmail.html
|
133
|
-
# e.g.) Received: (qmail 12345 invoked for bounce); 29 Apr 2009 12:34:56 -0000
|
134
|
-
# Subject: failure notice
|
135
|
-
tryto = [['(qmail ', 'invoked for bounce)'], ['(qmail ', 'invoked from ', 'network)']].freeze
|
136
|
-
match = 0
|
137
|
-
match += 1 if mhead['subject'].start_with?('failure notice', 'Permanent Delivery Failure')
|
138
|
-
mhead['received'].each do |e|
|
139
|
-
# Received: (qmail 2222 invoked for bounce);29 Apr 2017 23:34:45 +0900
|
140
|
-
# Received: (qmail 2202 invoked from network); 29 Apr 2018 00:00:00 +0900
|
141
|
-
match += 1 if tryto.any? { |a| Sisimai::String.aligned(e, a) }
|
142
|
-
end
|
143
|
-
return nil unless match > 0
|
144
|
-
|
145
|
-
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
146
|
-
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
147
|
-
bodyslices = emailparts[0].split("\n")
|
148
|
-
readcursor = 0 # (Integer) Points the current cursor position
|
149
|
-
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
150
|
-
v = nil
|
151
|
-
|
152
|
-
while e = bodyslices.shift do
|
153
|
-
# Read error messages and delivery status lines from the head of the email to the previous
|
154
|
-
# line of the beginning of the original message.
|
155
|
-
if readcursor == 0
|
156
|
-
# Beginning of the bounce message or delivery status part
|
157
|
-
readcursor |= Indicators[:deliverystatus] if StartingOf[:message].any? { |a| e.include?(a) }
|
158
|
-
next
|
159
|
-
end
|
160
|
-
next if (readcursor & Indicators[:deliverystatus]) == 0
|
161
|
-
next if e.empty?
|
162
|
-
|
163
|
-
# <kijitora@example.jp>:
|
164
|
-
# 192.0.2.153 does not like recipient.
|
165
|
-
# Remote host said: 550 5.1.1 <kijitora@example.jp>... User Unknown
|
166
|
-
# Giving up on 192.0.2.153.
|
167
|
-
v = dscontents[-1]
|
168
|
-
|
169
|
-
if e.start_with?('<') && Sisimai::String.aligned(e, ['<', '@', '>', ':'])
|
170
|
-
# <kijitora@example.jp>:
|
171
|
-
if v['recipient']
|
172
|
-
# There are multiple recipient addresses in the message body.
|
173
|
-
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
174
|
-
v = dscontents[-1]
|
175
|
-
end
|
176
|
-
v['recipient'] = Sisimai::Address.s3s4(e[e.index('<'), e.size])
|
177
|
-
recipients += 1
|
178
|
-
|
179
|
-
elsif dscontents.size == recipients
|
180
|
-
# Append error message
|
181
|
-
next if e.empty?
|
182
|
-
v['diagnosis'] ||= ''
|
183
|
-
v['diagnosis'] << e + ' '
|
184
|
-
v['alterrors'] = e if e.start_with?(StartingOf[:error][0])
|
185
|
-
|
186
|
-
next if v['rhost']
|
187
|
-
StartingOf[:rhost].each do |r|
|
188
|
-
# Find a remote host name
|
189
|
-
p1 = e.index(r); next unless p1
|
190
|
-
cm = r.size
|
191
|
-
p2 = e.index(' ', p1 + cm + 1) || p2 = e.rindex('.')
|
192
|
-
|
193
|
-
v['rhost'] = e[p1 + cm, p2 - p1 - cm]
|
194
|
-
break
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
return nil unless recipients > 0
|
199
|
-
|
200
|
-
dscontents.each do |e|
|
201
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
202
|
-
|
203
|
-
unless e['command']
|
204
|
-
# Get the SMTP command name for the session
|
205
|
-
CommandSet.each_key do |r|
|
206
|
-
# Verify each regular expression of SMTP commands
|
207
|
-
next unless CommandSet[r].any? { |a| e['diagnosis'].include?(a) }
|
208
|
-
e['command'] = r.upcase
|
209
|
-
break
|
210
|
-
end
|
211
|
-
|
212
|
-
if e['diagnosis'].include?('Sorry, no SMTP connection got far enough; most progress was ')
|
213
|
-
# Get the last SMTP command:from the error message
|
214
|
-
e['command'] ||= Sisimai::SMTP::Command.find(e['diagnosis']) || ''
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
# Detect the reason of bounce
|
219
|
-
if e['command'] == 'MAIL'
|
220
|
-
# MAIL | Connected to 192.0.2.135 but sender was rejected.
|
221
|
-
e['reason'] = 'rejected'
|
222
|
-
|
223
|
-
elsif %w[HELO EHLO].index(e['command'])
|
224
|
-
# HELO | Connected to 192.0.2.135 but my name was rejected.
|
225
|
-
e['reason'] = 'blocked'
|
226
|
-
else
|
227
|
-
# Try to match with each error message in the table
|
228
|
-
if Sisimai::String.aligned(e['diagnosis'], OnHoldPair)
|
229
|
-
# To decide the reason require pattern match with Sisimai::Reason::* modules
|
230
|
-
e['reason'] = 'onhold'
|
231
|
-
else
|
232
|
-
MessagesOf.each_key do |r|
|
233
|
-
# Verify each regular expression of session errors
|
234
|
-
if e['alterrors']
|
235
|
-
# Check the value of "alterrors"
|
236
|
-
next unless MessagesOf[r].any? { |a| e['alterrors'].include?(a) }
|
237
|
-
e['reason'] = r
|
238
|
-
end
|
239
|
-
break if e['reason']
|
240
|
-
|
241
|
-
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
|
242
|
-
e['reason'] = r
|
243
|
-
break
|
244
|
-
end
|
245
|
-
|
246
|
-
unless e['reason']
|
247
|
-
FailOnLDAP.each_key do |r|
|
248
|
-
# Verify each regular expression of LDAP errors
|
249
|
-
next unless FailOnLDAP[r].any? { |a| e['diagnosis'].include?(a) }
|
250
|
-
e['reason'] = r
|
251
|
-
break
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
unless e['reason']
|
256
|
-
e['reason'] = 'expired' if e['diagnosis'].include?(HasExpired)
|
257
|
-
end
|
258
|
-
end
|
259
|
-
end
|
260
|
-
e['command'] ||= Sisimai::SMTP::Command.find(e['diagnosis'])
|
261
|
-
end
|
262
|
-
|
263
|
-
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
264
|
-
end
|
265
|
-
def description; return 'Unknown MTA #4'; end
|
266
|
-
end
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
data/lib/sisimai/lhost/x5.rb
DELETED
@@ -1,112 +0,0 @@
|
|
1
|
-
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::X5 parses a bounce email which created by Unknown MTA #5. Methods in the module
|
3
|
-
# are called from only Sisimai::Message.
|
4
|
-
module X5
|
5
|
-
class << self
|
6
|
-
require 'sisimai/lhost'
|
7
|
-
|
8
|
-
Indicators = Sisimai::Lhost.INDICATORS
|
9
|
-
Boundaries = ['Content-Type: message/rfc822'].freeze
|
10
|
-
StartingOf = { message: ['Content-Type: message/delivery-status'] }.freeze
|
11
|
-
|
12
|
-
# Parse bounce messages from Unknown MTA #5
|
13
|
-
# @param [Hash] mhead Message headers of a bounce email
|
14
|
-
# @param [String] mbody Message body of a bounce email
|
15
|
-
# @return [Hash] Bounce data list and message/rfc822 part
|
16
|
-
# @return [Nil] it failed to parse or the arguments are missing
|
17
|
-
def inquire(mhead, mbody)
|
18
|
-
match = 0
|
19
|
-
match += 1 if mhead['to'].to_s.include?('NotificationRecipients')
|
20
|
-
if mhead['from'].include?('TWFpbCBEZWxpdmVyeSBTdWJzeXN0ZW0')
|
21
|
-
# From: "=?iso-2022-jp?B?TWFpbCBEZWxpdmVyeSBTdWJzeXN0ZW0=?=" <...>
|
22
|
-
# Mail Delivery Subsystem
|
23
|
-
mhead['from'].split(' ').each do |f|
|
24
|
-
# Check each element of From: header
|
25
|
-
next unless Sisimai::RFC2045.is_encoded(f)
|
26
|
-
match += 1 if Sisimai::RFC2045.decodeH([f]).include?('Mail Delivery Subsystem')
|
27
|
-
break
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
if Sisimai::RFC2045.is_encoded(mhead['subject'])
|
32
|
-
# Subject: =?iso-2022-jp?B?UmV0dXJuZWQgbWFpbDogVXNlciB1bmtub3du?=
|
33
|
-
plain = Sisimai::RFC2045.decodeH([mhead['subject']])
|
34
|
-
match += 1 if plain.include?('Mail Delivery Subsystem')
|
35
|
-
end
|
36
|
-
return nil if match < 2
|
37
|
-
|
38
|
-
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
39
|
-
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
40
|
-
readslices = ['']
|
41
|
-
readcursor = 0 # (Integer) Points the current cursor position
|
42
|
-
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
43
|
-
v = nil
|
44
|
-
|
45
|
-
# Pick the second message/rfc822 part because the format of email-x5-*.eml is nested structure
|
46
|
-
cutsbefore = mbody.split(Boundaries[0], 2)
|
47
|
-
cutsbefore[1] = cutsbefore[1][cutsbefore[1].index("\n\n") + 2, cutsbefore[1].size]
|
48
|
-
emailparts = Sisimai::RFC5322.part(cutsbefore[1], Boundaries)
|
49
|
-
bodyslices = emailparts[0].split("\n")
|
50
|
-
|
51
|
-
while e = bodyslices.shift do
|
52
|
-
# Read error messages and delivery status lines from the head of the email to the previous
|
53
|
-
# line of the beginning of the original message.
|
54
|
-
readslices << e # Save the current line for the next loop
|
55
|
-
|
56
|
-
if readcursor == 0
|
57
|
-
# Beginning of the bounce message or message/delivery-status part
|
58
|
-
readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
|
59
|
-
next
|
60
|
-
end
|
61
|
-
next if (readcursor & Indicators[:deliverystatus]) == 0
|
62
|
-
next if e.empty?
|
63
|
-
|
64
|
-
v = dscontents[-1]
|
65
|
-
if f = Sisimai::RFC1894.match(e)
|
66
|
-
# "e" matched with any field defined in RFC3464
|
67
|
-
next unless o = Sisimai::RFC1894.field(e)
|
68
|
-
v = dscontents[-1]
|
69
|
-
|
70
|
-
if o[-1] == 'addr'
|
71
|
-
# Final-Recipient: rfc822; kijitora@example.jp
|
72
|
-
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
73
|
-
if o[0] == 'final-recipient'
|
74
|
-
# Final-Recipient: rfc822; kijitora@example.jp
|
75
|
-
if v['recipient']
|
76
|
-
# There are multiple recipient addresses in the message body.
|
77
|
-
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
78
|
-
v = dscontents[-1]
|
79
|
-
end
|
80
|
-
v['recipient'] = o[2]
|
81
|
-
recipients += 1
|
82
|
-
else
|
83
|
-
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
84
|
-
v['alias'] = o[2]
|
85
|
-
end
|
86
|
-
elsif o[-1] == 'code'
|
87
|
-
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
88
|
-
v['spec'] = o[1]
|
89
|
-
v['diagnosis'] = o[2]
|
90
|
-
else
|
91
|
-
# Other DSN fields defined in RFC3464
|
92
|
-
next unless fieldtable[o[0]]
|
93
|
-
v[fieldtable[o[0]]] = o[2]
|
94
|
-
end
|
95
|
-
else
|
96
|
-
# Continued line of the value of Diagnostic-Code field
|
97
|
-
next unless readslices[-2].start_with?('Diagnostic-Code:')
|
98
|
-
next unless e.start_with?(' ')
|
99
|
-
v['diagnosis'] << ' ' << Sisimai::String.sweep(e)
|
100
|
-
readslices[-1] = 'Diagnostic-Code: ' << e
|
101
|
-
end
|
102
|
-
end
|
103
|
-
return nil unless recipients > 0
|
104
|
-
|
105
|
-
dscontents.each { |e| e['diagnosis'] ||= Sisimai::String.sweep(e['diagnosis']) }
|
106
|
-
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
107
|
-
end
|
108
|
-
def description; return 'Unknown MTA #5'; end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
data/lib/sisimai/lhost/yahoo.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::Yahoo parses a bounce email which created by Yahoo! MAIL. Methods in the module
|
3
|
-
# are called from only Sisimai::Message.
|
4
|
-
module Yahoo
|
5
|
-
class << self
|
6
|
-
require 'sisimai/lhost'
|
7
|
-
|
8
|
-
Indicators = Sisimai::Lhost.INDICATORS
|
9
|
-
Boundaries = ['--- Below this line is a copy of the message.'].freeze
|
10
|
-
StartingOf = { message: ['Sorry, we were unable to deliver your message'] }.freeze
|
11
|
-
|
12
|
-
# Parse bounce messages from Yahoo! MAIL
|
13
|
-
# @param [Hash] mhead Message headers of a bounce email
|
14
|
-
# @param [String] mbody Message body of a bounce email
|
15
|
-
# @return [Hash] Bounce data list and message/rfc822 part
|
16
|
-
# @return [Nil] it failed to parse or the arguments are missing
|
17
|
-
def inquire(mhead, mbody)
|
18
|
-
# X-YMailISG: YtyUVyYWLDsbDh...
|
19
|
-
# X-YMail-JAS: Pb65aU4VM1mei...
|
20
|
-
# X-YMail-OSG: bTIbpDEVM1lHz...
|
21
|
-
# X-Originating-IP: [192.0.2.9]
|
22
|
-
return nil unless mhead['x-ymailisg']
|
23
|
-
|
24
|
-
require 'sisimai/smtp/command'
|
25
|
-
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
26
|
-
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
27
|
-
bodyslices = emailparts[0].split("\n")
|
28
|
-
readcursor = 0 # (Integer) Points the current cursor position
|
29
|
-
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
30
|
-
v = nil
|
31
|
-
|
32
|
-
while e = bodyslices.shift do
|
33
|
-
# Read error messages and delivery status lines from the head of the email to the previous
|
34
|
-
# line of the beginning of the original message.
|
35
|
-
if readcursor == 0
|
36
|
-
# Beginning of the bounce message or delivery status part
|
37
|
-
readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
|
38
|
-
next
|
39
|
-
end
|
40
|
-
next if (readcursor & Indicators[:deliverystatus]) == 0
|
41
|
-
next if e.empty?
|
42
|
-
|
43
|
-
# Sorry, we were unable to deliver your message to the following address.
|
44
|
-
#
|
45
|
-
# <kijitora@example.org>:
|
46
|
-
# Remote host said: 550 5.1.1 <kijitora@example.org>... User Unknown [RCPT_TO]
|
47
|
-
v = dscontents[-1]
|
48
|
-
|
49
|
-
if e.start_with?('<') && Sisimai::String.aligned(e, ['<', '@', '>:'])
|
50
|
-
# <kijitora@example.org>:
|
51
|
-
if v['recipient']
|
52
|
-
# There are multiple recipient addresses in the message body.
|
53
|
-
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
54
|
-
v = dscontents[-1]
|
55
|
-
end
|
56
|
-
v['recipient'] = Sisimai::Address.s3s4(e[0, e.index('>:')])
|
57
|
-
v['diagnosis'] = ''
|
58
|
-
recipients += 1
|
59
|
-
|
60
|
-
else
|
61
|
-
if e.start_with?('Remote host said:')
|
62
|
-
# Remote host said: 550 5.1.1 <kijitora@example.org>... User Unknown [RCPT_TO]
|
63
|
-
v['diagnosis'] = e
|
64
|
-
|
65
|
-
# Get SMTP command from the value of "Remote host said:"
|
66
|
-
v['command'] = Sisimai::SMTP::Command.find(e)
|
67
|
-
else
|
68
|
-
# <mailboxfull@example.jp>:
|
69
|
-
# Remote host said:
|
70
|
-
# 550 5.2.2 <mailboxfull@example.jp>... Mailbox Full
|
71
|
-
# [RCPT_TO]
|
72
|
-
if v['diagnosis'].start_with?('Remote host said:')
|
73
|
-
# Remote host said:
|
74
|
-
# 550 5.2.2 <mailboxfull@example.jp>... Mailbox Full
|
75
|
-
if cv = Sisimai::SMTP::Command.find(e)
|
76
|
-
# [RCPT_TO]
|
77
|
-
v['command'] = cv
|
78
|
-
else
|
79
|
-
# 550 5.2.2 <mailboxfull@example.jp>... Mailbox Full
|
80
|
-
v['diagnosis'] = e
|
81
|
-
end
|
82
|
-
else
|
83
|
-
# Error message which does not start with 'Remote host said:'
|
84
|
-
v['diagnosis'] << ' ' << e
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
return nil unless recipients > 0
|
90
|
-
|
91
|
-
dscontents.each do |e|
|
92
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].gsub(/\\n/, ' '))
|
93
|
-
e['command'] ||= 'RCPT' if Sisimai::String.aligned(e['diagnosis'], ['<', '@', '>'])
|
94
|
-
end
|
95
|
-
|
96
|
-
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
97
|
-
end
|
98
|
-
def description; return 'Yahoo! MAIL: https://www.yahoo.com'; end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
data/lib/sisimai/lhost/yandex.rb
DELETED
@@ -1,118 +0,0 @@
|
|
1
|
-
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::Yandex parses a bounce email which created by Yandex.Mail. Methods in the module
|
3
|
-
# are called from only Sisimai::Message.
|
4
|
-
module Yandex
|
5
|
-
class << self
|
6
|
-
require 'sisimai/lhost'
|
7
|
-
|
8
|
-
Indicators = Sisimai::Lhost.INDICATORS
|
9
|
-
Boundaries = ['Content-Type: message/rfc822'].freeze
|
10
|
-
StartingOf = { message: ['This is the mail system at host yandex.ru.'] }.freeze
|
11
|
-
|
12
|
-
# Parse bounce messages from Yandex.Mail
|
13
|
-
# @param [Hash] mhead Message headers of a bounce email
|
14
|
-
# @param [String] mbody Message body of a bounce email
|
15
|
-
# @return [Hash] Bounce data list and message/rfc822 part
|
16
|
-
# @return [Nil] it failed to parse or the arguments are missing
|
17
|
-
def inquire(mhead, mbody)
|
18
|
-
# X-Yandex-Front: mxback1h.mail.yandex.net
|
19
|
-
# X-Yandex-TimeMark: 1417885948
|
20
|
-
# X-Yandex-Uniq: 92309766-f1c8-4bd4-92bc-657c75766587
|
21
|
-
# X-Yandex-Spam: 1
|
22
|
-
# X-Yandex-Forward: 10104c00ad0726da5f37374723b1e0c8
|
23
|
-
# X-Yandex-Queue-ID: 367D79E130D
|
24
|
-
# X-Yandex-Sender: rfc822; shironeko@yandex.example.com
|
25
|
-
return nil unless mhead['x-yandex-uniq']
|
26
|
-
return nil unless mhead['from'] == 'mailer-daemon@yandex.ru'
|
27
|
-
|
28
|
-
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
29
|
-
permessage = {} # (Hash) Store values of each Per-Message field
|
30
|
-
|
31
|
-
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
32
|
-
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
33
|
-
bodyslices = emailparts[0].split("\n")
|
34
|
-
readslices = ['']
|
35
|
-
readcursor = 0 # (Integer) Points the current cursor position
|
36
|
-
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
37
|
-
commandset = [] # (Array) ``in reply to * command'' list
|
38
|
-
v = nil
|
39
|
-
|
40
|
-
while e = bodyslices.shift do
|
41
|
-
# Read error messages and delivery status lines from the head of the email to the previous
|
42
|
-
# line of the beginning of the original message.
|
43
|
-
readslices << e # Save the current line for the next loop
|
44
|
-
|
45
|
-
if readcursor == 0
|
46
|
-
# Beginning of the bounce message or message/delivery-status part
|
47
|
-
readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
|
48
|
-
next
|
49
|
-
end
|
50
|
-
next if (readcursor & Indicators[:deliverystatus]) == 0
|
51
|
-
next if e.empty?
|
52
|
-
|
53
|
-
if f = Sisimai::RFC1894.match(e)
|
54
|
-
# "e" matched with any field defined in RFC3464
|
55
|
-
next unless o = Sisimai::RFC1894.field(e)
|
56
|
-
v = dscontents[-1]
|
57
|
-
|
58
|
-
if o[-1] == 'addr'
|
59
|
-
# Final-Recipient: rfc822; kijitora@example.jp
|
60
|
-
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
61
|
-
if o[0] == 'final-recipient'
|
62
|
-
# Final-Recipient: rfc822; kijitora@example.jp
|
63
|
-
if v['recipient']
|
64
|
-
# There are multiple recipient addresses in the message body.
|
65
|
-
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
66
|
-
v = dscontents[-1]
|
67
|
-
end
|
68
|
-
v['recipient'] = o[2]
|
69
|
-
recipients += 1
|
70
|
-
else
|
71
|
-
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
72
|
-
v['alias'] = o[2]
|
73
|
-
end
|
74
|
-
elsif o[-1] == 'code'
|
75
|
-
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
76
|
-
v['spec'] = o[1]
|
77
|
-
v['diagnosis'] = o[2]
|
78
|
-
else
|
79
|
-
# Other DSN fields defined in RFC3464
|
80
|
-
next unless fieldtable[o[0]]
|
81
|
-
v[fieldtable[o[0]]] = o[2]
|
82
|
-
|
83
|
-
next unless f
|
84
|
-
permessage[fieldtable[o[0]]] = o[2]
|
85
|
-
end
|
86
|
-
else
|
87
|
-
# The line does not begin with a DSN field defined in RFC3464
|
88
|
-
if e.include?(' (in reply to ') || e.include?('command)')
|
89
|
-
# 5.1.1 <userunknown@example.co.jp>... User Unknown (in reply to RCPT TO
|
90
|
-
cv = Sisimai::SMTP::Command.find(e)
|
91
|
-
commandset << cv if cv
|
92
|
-
|
93
|
-
else
|
94
|
-
# Continued line of the value of Diagnostic-Code field
|
95
|
-
next unless readslices[-2].start_with?('Diagnostic-Code:')
|
96
|
-
next unless e.start_with?(' ')
|
97
|
-
v['diagnosis'] << ' ' << Sisimai::String.sweep(e)
|
98
|
-
readslices[-1] = 'Diagnostic-Code: ' << e
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
return nil unless recipients > 0
|
103
|
-
|
104
|
-
dscontents.each do |e|
|
105
|
-
# Set default values if each value is empty.
|
106
|
-
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
107
|
-
|
108
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].tr("\n", ' '))
|
109
|
-
e['command'] ||= commandset.shift || Sisimai::SMTP::Command.find(e['diagnosis']) || ''
|
110
|
-
end
|
111
|
-
|
112
|
-
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
113
|
-
end
|
114
|
-
def description; return 'Yandex.Mail: https://www.yandex.ru'; end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|