h&Q L      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST Safe-Inferred"U domain-authremoveBtagValue "DKIM-Signature: a=rsa-sha256; d=example.net; s=brisbane;\n c=simple; q=dns/txt; i=@eng.example.net;\n t=1117574938; x=1118006938;\n h=from:to:subject:date;\n z=From:foo@eng.example.net|To:joe@example.com|\n Subject:demo=20run|Date:July=205,=202005=203:44:08=20PM=20-0700;\n bh=MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=;\n b=dzdVyOfAKCdLXdJOc9G2q8LoXSlEniSbav+yuU4zGeeruD00lszZ\n VoG4ZHRNiYzR;\n""DKIM-Signature: a=rsa-sha256; d=example.net; s=brisbane;\n c=simple; q=dns/txt; i=@eng.example.net;\n t=1117574938; x=1118006938;\n h=from:to:subject:date;\n z=From:foo@eng.example.net|To:joe@example.com|\n Subject:demo=20run|Date:July=205,=202005=203:44:08=20PM=20-0700;\n bh=MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=;\n b=;\n"U Safe-Inferred|  domain-auth'Type for body of parsed e-mail message. domain-auth.Type for field value of parsed e-mail message. domain-auth,Type for field key of parsed e-mail message. domain-auth:Type for canonicalized field key of parsed e-mail message. domain-auth%Field type for parsed e-mail message.  domain-auth&Header type for parsed e-mail message.  domain-authType for parsed e-mail message. domain-auth"Body chunk for raw e-mail message. domain-auth#Field value for raw e-mail message. domain-auth!Field key for raw e-mail message. domain-authType for raw e-mail message. domain-authCanonicalizing  for search. VWX  Safe-Inferred" lY domain-authP.parseOnly structured "From: Kazu Yamamoto (=?iso-2022-jp?B?GyRCOzNLXE9CSScbKEI=?=)\n "Right ["From",":","Kazu","Yamamoto","<","kazu","@","example",".","net",">"]P.parseOnly structured "To:A Group(Some people)\n :Chris Jones ,\n joe@example.org,\n John (my dear friend); (the end of the group)\n"Right ["To",":","A","Group",":","Chris","Jones","<","c","@","public",".","example",">",",","joe","@","example",".","org",",","John","<","jdoe","@","one",".","test",">",";"]P.parseOnly structured "Date: Thu,\n 13\n Feb\n 1969\n 23:32\n -0330 (Newfoundland Time)\n"Right ["Date",":","Thu",",","13","Feb","1969","23",":","32","-0330"]P.parseOnly structured "From: Pete(A nice \\) chap) \n"?Right ["From",":","Pete","<","pete","@","silly",".","test",">"]Y  Safe-Inferred" Z[\]^_`abcdefghijklmno  Safe-Inferred" p  Safe-Inferred" q Safe-Inferred  domain-authThe result of domain authentication. For more information, see  #http://www.ietf.org/rfc/rfc5451.txt.      Safe-Inferred% domain-authLimit for SPF authentication.' domain-auth5How many "redirect"/"include" should be followed. & is returned if reached to this limit.( domain-auth;Ignoring IPv4 range whose mask length is shorter than this.) domain-auth;Ignoring IPv6 range whose mask length is shorter than this.* domain-auth"Whether or not "+all" is rejected.+ domain-authDefault value for %. defaultLimitLimit {limit = 10, ipv4_masklen = 16, ipv6_masklen = 48, reject_plus_all = True}%&'()*+r Safe-Inferred%, domain-authProcess SPF authentication. s) is an IP address of an SMTP peer. If t is specified from SMTP MAIL FROM, authentication is based on SPF. If t is specified from the From field of mail header, authentication is based on SenderID. If condition reaches %,  SpfPermError is returned.&rs <- makeResolvSeed defaultResolvConfpass (IPv4 & IPv6):withResolver rs $ \rslv -> runSPF defaultLimit rslv "mew.org" "202.238.220.92"passwithResolver rs $ \rslv -> runSPF defaultLimit rslv "iij.ad.jp" "2001:240:bb5f:86c::1:41"pass hardfail:withResolver rs $ \rslv -> runSPF defaultLimit rslv "example.org" "192.0.2.1"hardfailredirect and include:withResolver rs $ \rslv -> runSPF defaultLimit rslv "gmail.com" "72.14.192.1"passwithResolver rs $ \rslv -> runSPF defaultLimit rslv "gmail.com" "72.14.128.1"softfaillimit:/let limit1 = defaultLimit { ipv4_masklen = 24 }withResolver rs $ \rslv -> runSPF limit1 rslv "gmail.com" "72.14.192.1"softfail%&'()*+,,%&'()*+ Safe-Inferred"u domain-auth&Replaces multiple WPSs to a single SP.v domain-authblines "foo\r\n\r\nbar\r\nbaz"["foo","","bar","baz"]blines "foo\r\n"["foo"]%wxyz{|}~uv Safe-Inferred"] Safe-Inferred- domain-auth0Type for temporary data to parse e-mail message.1 domain-authInitial value for -.2 domain-auth8Storing field key and field value to the temporary data.3 domain-auth)Storing body chunk to the temporary data.4 domain-auth Converting - to  .-./01234 Safe-Inferred"+5 domain-authObtain   from a file.6 domain-authObtain   from .let out1 = finalizeMail $ pushBody "body" $ pushField "to" "val" $ pushField "from" "val" initialXMail,getMail "from: val\nto: val\n\nbody" == out1Truelet out2 = finalizeMail $ pushBody "body" $ pushField "to" "val" $ pushField "from" "val\tval" initialXMail1getMail "from: val\tval\nto: val\n\nbody" == out2Truelet out3 = finalizeMail $ pushBody "" $ pushField "to" "val" $ pushField "from" "val" initialXMail&getMail "from: val\nto: val\n" == out3True7 domain-auth!Parsing field value of tag=value. domain-authObtaining body.? domain-auth0Obtaining body with a canonicalization function.@ domain-authRemoving trailing empty lines. 89:;<=>?@ Safe-Inferred#( -./0123456789:;<=>?@( 56-./0123489:;<=>?@7 Safe-Inferred")z domain-authLooking up an RSA public key.rs <- DNS.makeResolvSeed DNS.defaultResolvConfwithResolver rs $ \rslv -> lookupPublicKey rslv "dk200510._domainkey.yahoo.co.jp"Just (PublicKey {public_size = 128, public_n = 124495277115430906234131617223399742059624761592171426860362133400468320289284068350453787798555522712914036293436636386707903510390018044090096883314714401752103035965668114514933570840775088208966674120428191313530595210688523478828022953238411688594634270571841869051696953556782155414877029327479844990933, public_e = 65537})withResolver rs $ \rslv -> lookupPublicKey rslv "20221208._domainkey.gmail.com"Just (PublicKey {public_size = 256, public_n = 22678151869562939359899136428859256198402569240680475393086048829021713182010490409724483359945551283969506235489826762257419985891230334120904178414351809046671461143996599803281758436654811035615578092428632166371331342907633917876752170113620966009358291594609542956251740141784694619901495773614035042135465203364073740861194611021551592336450807473519143746970021740067888325723330796836146546417386918505126721680365151889317110944800331756379997471380657912089911948147086686452887197011845657708078311037666769039161141500897109834073427400667740315220146696437513966171590587213846521825862509466370365529359, public_e = 65537}) Safe-Inferred"+A domain-auth0Extract a domain from a value of a header field.5extractDomain "Alice Brown "Just "example.com"extractDomain "\"Alice . Brown\" (Nickname here)"Just "example.com"'extractDomain "alice.brown@example.com"Just "example.com")extractDomain "Alice Brown "NothingA Safe-Inferred"4B domain-authAbstract type for context to decide PRD(purported responsible domain) according to RFC 4407.C domain-authInitial context of PRD.D domain-auth8Pushing a field key and its value in to the PRD context.E domain-auth"Deciding PRD from the RPD context.%let maddr1 = "alice@alice.example.jp"!let maddr2 = "bob@bob.example.jp"%let maddr3 = "chris@chris.example.jp"#let maddr4 = "dave@dave.example.jp">decidePRD (pushPRD "from" "alice@alice.example.jp" initialPRD)Just "alice.example.jp":{ decidePRD (pushPRD "from" maddr1, $ pushPRD "from" maddr1 initialPRD):}Nothing:{"decidePRD (pushPRD "sender" maddr2 $ pushPRD "from" maddr1, $ pushPRD "from" maddr1 initialPRD):}Just "bob.example.jp":{"decidePRD (pushPRD "sender" maddr2" $ pushPRD "sender" maddr2 $ pushPRD "from" maddr1, $ pushPRD "from" maddr1 initialPRD):}Nothing:{'decidePRD (pushPRD "resent-from" maddr3" $ pushPRD "sender" maddr2" $ pushPRD "sender" maddr2 $ pushPRD "from" maddr1, $ pushPRD "from" maddr1 initialPRD):}Just "chris.example.jp":{)decidePRD (pushPRD "resent-sender" maddr4( $ pushPRD "resent-from" maddr3# $ pushPRD "sender" maddr2# $ pushPRD "sender" maddr2! $ pushPRD "from" maddr1- $ pushPRD "from" maddr1 initialPRD):}Just "dave.example.jp":{)decidePRD (pushPRD "resent-sender" maddr4' $ pushPRD "resent-from" maddr3" $ pushPRD "sender" maddr2% $ pushPRD "received" "dummy", $ pushPRD "from" maddr1 initialPRD):}Just "dave.example.jp":{)decidePRD (pushPRD "resent-sender" maddr4% $ pushPRD "received" "dummy"' $ pushPRD "resent-from" maddr3" $ pushPRD "sender" maddr2, $ pushPRD "from" maddr1 initialPRD):}Just "chris.example.jp":{%decidePRD (pushPRD "received" "dummy"* $ pushPRD "resent-sender" maddr4( $ pushPRD "resent-from" maddr3# $ pushPRD "sender" maddr2- $ pushPRD "from" maddr1 initialPRD):}Just "dave.example.jp"F domain-auth/Taking the value of From: from the RPD context.?decideFrom (pushPRD "from" "alice@alice.example.jp" initialPRD)Just "alice.example.jp"BCDEF Safe-Inferred4=ABCDEFBCDEFA Safe-Inferred"5:H domain-auth&Canonicalized key for DKIM-Signature:.I domain-auth7Getting of the value of the "d" tag in DKIM-Signature:.J domain-auth7Getting of the value of the "s" tag in DKIM-Signature:.GHIJ Safe-Inferred"@K domain-authParsing DKIM-Signature:.:{!let dkim = BS8.concat [ "v=1; a=rsa-sha256; s=brisbane; d=example.com;\n" , " c=relaxed/simple; q=dns/txt; i=joe@football.example.com;\n" , " h=Received : From : To : Subject : Date : Message-ID;\n" , " bh=2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=;\n" , " b=AuUoFEfDxTDkHlLXSZEpZj79LICEps6eda7W3deTVFOk4yAUoqOB\n" , " 4nujc7YopdG5dWLSdNg6xNAZpOPr+kHxt1IrE+NahM6L/LbvaHut\n" , " KVdkLLkpVaVVQPzeRDI009SO2Il5Lu7rDNH6mZckBdrIx0orEtZV\n"0 , " 4bmp/YzhwvcubU4=;" ]!in pPrintNoColor $ parseDKIM dkim:}Just ( DKIM  { dkimVersion = "1"" , dkimSigAlgo = RSA_SHA256 , dkimSignature = "AuUoFEfDxTDkHlLXSZEpZj79LICEps6eda7W3deTVFOk4yAUoqOB4nujc7YopdG5dWLSdNg6xNAZpOPr+kHxt1IrE+NahM6L/LbvaHutKVdkLLkpVaVVQPzeRDI009SO2Il5Lu7rDNH6mZckBdrIx0orEtZV4bmp/YzhwvcubU4=" , dkimBodyHash = "2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8="( , dkimHeaderCanon = DKIM_RELAXED% , dkimBodyCanon = DKIM_SIMPLE% , dkimDomain0 = "example.com" , dkimFields =  [ "received" , "from" , "to" , "subject" , "date" , "message-id" ]  , dkimLength = Nothing$ , dkimSelector0 = "brisbane" }  ):{!let dkim = BS8.concat [ "v=1; a=rsa-sha256; s=brisbane; d=example.com;\n" , " q=dns/txt; i=joe@football.example.com;\n" , " h=Received : From : To : Subject : Date : Message-ID;\n" , " bh=2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=;\n" , " b=AuUoFEfDxTDkHlLXSZEpZj79LICEps6eda7W3deTVFOk4yAUoqOB\n" , " 4nujc7YopdG5dWLSdNg6xNAZpOPr+kHxt1IrE+NahM6L/LbvaHut\n" , " KVdkLLkpVaVVQPzeRDI009SO2Il5Lu7rDNH6mZckBdrIx0orEtZV\n"/ , " 4bmp/YzhwvcubU4=;" ]!in pPrintNoColor $ parseDKIM dkim:}Just ( DKIM  { dkimVersion = "1"" , dkimSigAlgo = RSA_SHA256 , dkimSignature = "AuUoFEfDxTDkHlLXSZEpZj79LICEps6eda7W3deTVFOk4yAUoqOB4nujc7YopdG5dWLSdNg6xNAZpOPr+kHxt1IrE+NahM6L/LbvaHutKVdkLLkpVaVVQPzeRDI009SO2Il5Lu7rDNH6mZckBdrIx0orEtZV4bmp/YzhwvcubU4=" , dkimBodyHash = "2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8="' , dkimHeaderCanon = DKIM_SIMPLE% , dkimBodyCanon = DKIM_SIMPLE% , dkimDomain0 = "example.com" , dkimFields =  [ "received" , "from" , "to" , "subject" , "date" , "message-id" ]  , dkimLength = Nothing$ , dkimSelector0 = "brisbane" }  )K Safe-Inferred"B.L domain-auth&Abstract type for DomainKey-Signature:M domain-auth+Canonicalized key for DomainKey-Signature:.N domain-auth"2 ,"Date: Thu, 17 Aug 2023 11:33:46 +0900": ,"From: Kazu Yamamoto " ,"MIME-Version: 1.0"8 ,"Content-Type: text/plain; charset=\"UTF-8\"" ,"" ,"test" ]/ mail = getMail $ BS8.intercalate "\r\n" lst/in withResolver rs $ \rslv -> runDKIM rslv mail:}passR domain-auth Verifying   with DKIM. The value of DKIM-Signature: should be parsed beforehand.GHIJKQRQRKGIJH Safe-Inferred"K Safe-Inferred"LdS domain-auth Verifying   with DomainKeys.T domain-auth Verifying   with DomainKeys. The value of DomainKey-Signature: should be parsed beforehand.LMNOPSTSTPLNOM Safe-InferredL  %*)(&'+,-0./123456789:;<=>?@ABCDEFGHIJKLMNOPQRST !!"#$%&&'()*+,-./0123456789:;<=>? @ @ A B C D EFGGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopq r s t u v w x y z { | } ~             `e(domain-auth-0.2.3-JFDZrnFf3WEBr8zEmEhsiFNetwork.DomainAuth.MailNetwork.DomainAuth.TypesNetwork.DomainAuth.SPFNetwork.DomainAuth.PRDNetwork.DomainAuth.DKIMNetwork.DomainAuth.DKNetwork.DomainAuth.DKIM.BtagNetwork.DomainAuth.Mail.TypesNetwork.DomainAuth.PRD.LexerNetwork.DomainAuth.SPF.TypesNetwork.DomainAuth.SPF.ParserNetwork.DomainAuth.SPF.ResolverNetwork.DomainAuth.SPF.EvalNetwork.DomainAuth.Utils Network.DomainAuth.Pubkey.Base64Network.DomainAuth.Mail.XMailNetwork.DomainAuth.Mail.ParserNetwork.DomainAuth.Mail.Mail Network.DomainAuth.Pubkey.RSAPubNetwork.DomainAuth.PRD.DomainNetwork.DomainAuth.PRD.PRDNetwork.DomainAuth.DKIM.TypesNetwork.DomainAuth.DKIM.ParserNetwork.DomainAuth.DK.TypesNetwork.DomainAuth.DK.ParserNetwork.DomainAuth.DKIM.VerifyNetwork.DomainAuth.DK.VerifyNetwork.DomainAuthBody FieldValueFieldKey CanonFieldKeyFieldfieldSearchKeyfieldKey fieldValueHeaderMail mailHeadermailBody RawBodyChunk RawFieldValue RawFieldKeyRawMailisEmptycanonicalizeKeyDAResultDAPass DAHardFail DASoftFail DANeutralDAFail DATempError DAPermErrorDANoneDAPolicy DANxDomain DADiscard DAUnknown$fShowDAResult $fEqDAResult$fEnumDAResult$fBoundedDAResultLimitlimit ipv4_masklen ipv6_masklenreject_plus_all defaultLimitrunSPFXMail xmailHeader xmailBody initialXMail pushFieldpushBody finalizeMailreadMailgetMailparseTaggedValue lookupField fieldsFrom fieldsAfter fieldsWithfieldValueFoldedfieldValueUnfoldedfromBody fromBodyWithremoveTrailingEmptyLine extractDomainPRD initialPRDpushPRD decidePRD decideFromDKIM dkimFieldKey dkimDomain dkimSelector parseDKIMDK dkFieldKeydkDomain dkSelectorparseDKrunDKIMrunDKIM'runDKrunDK'removeBtagValueRawFieldRawBody RawHeader structuredSpfSeq SS_SpfSeq SS_IF_Pass SS_IPv6Ranges SS_IPv4Ranges SS_IPv6Range SS_IPv4RangeSS_AllSPF SPF_RedirectSPF_All SPF_IncludeSPF_MX SPF_Address SPF_IPv6Range SPF_IPv4Range Qualifier Q_Neutral Q_Softfail Q_HardFailQ_PassqualifierSymbolparseSPF resolveSPFevalSPF%iproute-1.7.12-JkrD2R1HJObDbAyuc1LFUA Data.IP.AddrIP-dns-4.2.0-31EJR1t9s9ALiUzwC1VYXM-dns-internalNetwork.DNS.Types.InternalDomain reduceWSPblinesCook FWSRemovercrlf+++empty!!! appendCRLF appendCRLF'appendCRLFWith concatCRLFconcatCRLFWithinSPoutSP removeFWSremoveTrailingWSPhasTrailingWSPchopbreak' isAlphaNumisDigitisUpperisLowerisSpacecCRcLFcSPcTBcPluscSlashcEqualcSmallAcAcZerocColon cSemiColondecodedecode'enmlookupPublicKey dkimSelector0 dkimLength dkimFields dkimDomain0 dkimBodyCanondkimHeaderCanon dkimBodyHash dkimSignature dkimSigAlgo dkimVersion DkimCanonAlgo DKIM_RELAXED DKIM_SIMPLE DkimSigAlgo RSA_SHA256RSA_SHA1 dkSelector0dkFields dkDomain0 dkCanonAlgo dkSignature dkAlgorithmDkFields DkCanonAlgoDK_NOFWS DK_SIMPLE DkAlgorithm DK_RSA_SHA1 prepareDKIM verifyDKIM prepareDKverifyDK