@redsift/products 12.1.1-muiv6 → 12.2.0-muiv5
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.
- package/index.d.ts +24 -0
- package/index2.js +478 -144
- package/index2.js.map +1 -1
- package/package.json +6 -10
package/index2.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { _ as _objectSpread2, a as _objectWithoutProperties, b as _extends } from './_internal/_rollupPluginBabelHelpers.js';
|
|
2
2
|
import React__default, { useMemo, useContext, createContext, forwardRef, useCallback, Component, useState, useEffect, useId, useRef, Suspense, memo } from 'react';
|
|
3
|
-
import { mdiCheck, mdiAlert, mdiClose, mdiInformation, mdiHelpCircle, mdiEmail, mdiEarth, mdiArrowDownBold } from '@redsift/icons';
|
|
3
|
+
import { mdiCheck, mdiAlert, mdiClose, mdiInformation, mdiHelpCircle, mdiEmail, mdiEarth, mdiInformationOutline, mdiArrowDownBold } from '@redsift/icons';
|
|
4
4
|
import styled, { css } from 'styled-components';
|
|
5
5
|
import { useLocalizedStringFormatter, useTheme, Button, Icon, DetailedCard, Flexbox, Link, TextField } from '@redsift/design-system';
|
|
6
6
|
import classNames from 'classnames';
|
|
@@ -562,6 +562,7 @@ var enUS = {
|
|
|
562
562
|
"investigate.card.bimi.record-passed_md": "**[](BIMI_RECORD#:glossary)** **Present and compliant**",
|
|
563
563
|
"investigate.card.bimi.record-declination_md": "**[](BIMI_RECORD#:glossary)** Present and containing a **valid declination to publish**",
|
|
564
564
|
"investigate.card.bimi.record-no-cert_md": "**[](BIMI_RECORD#:glossary)** **Certificate not found**",
|
|
565
|
+
"investigate.card.bimi.cert-forbidden_md": "Your certificate appears to be behind an anti-bot protection system. [Find out more and how to resolve the issue](https://knowledge.ondmarc.redsift.com/en/articles/8047013-ondmarc-cannot-fetch-my-bimi-logo-or-certificate)",
|
|
565
566
|
"investigate.card.bimi.record-failed_md": "**[](BIMI_RECORD#:glossary)** **Present** but with errors",
|
|
566
567
|
"investigate.card.bimi.record-missing_md": "**[](BIMI_RECORD#:glossary)** **Missing.** [Learn how to fix it](https://community.redsift.com/s/article/000001130)",
|
|
567
568
|
"investigate.card.bimi.could-not-fetch_md": "Failed to fetch **[](BIMI_RECORD#:glossary)**",
|
|
@@ -575,6 +576,7 @@ var enUS = {
|
|
|
575
576
|
"investigate.card.bimi.vmc.expiry-date_md": "**Expires on:** {date} ({daysLeft} days left)",
|
|
576
577
|
"investigate.card.bimi.vmc.expired-date_md": "Expired on {date}",
|
|
577
578
|
"investigate.card.bimi.vmc.trademarkAuthority_md": "**Trademark Authority: {trademarkAuthority}**",
|
|
579
|
+
"investigate.card.bimi.vmc.assertionMark_md": "**Assertion Mark:** {assertionMark}",
|
|
578
580
|
"investigate.card.bimi.logoErrors.invalid-svg_md": "**[](VMC#:glossary)** Invalid SVG. Logo from certificate cannot be converted to a valid SVG.",
|
|
579
581
|
"investigate.card.bimi.logoErrors.invalid-svg-version_md": "**[](VMC#:glossary)** Invalid SVG version. Should be **1.2**",
|
|
580
582
|
"investigate.card.bimi.logoErrors.invalid-svg-profile_md": "**[](VMC#:glossary)** Invalid SVG profile. Should be **tiny-ps**",
|
|
@@ -595,10 +597,11 @@ var enUS = {
|
|
|
595
597
|
"investigate.card.bimi.logoErrors.logo-and-evidence-mismatch_md": "**[](VMC#:glossary)** Logo on l record and on certificate do not match",
|
|
596
598
|
"investigate.card.bimi.logoErrors.logo-extract-error_md": "**[](VMC#:glossary)** Error extracting logo",
|
|
597
599
|
"investigate.card.bimi.logoErrors.unknown-svg-error_md": "**[](VMC#:glossary)** Unknown SVG error",
|
|
600
|
+
"investigate.card.bimi.svg-error-fallback_md": "**[](VMC#:glossary)** {error}",
|
|
598
601
|
"investigate.card.bimi.pemErrors.cert-not-found_md": "**[](VMC#:glossary)** Certificate not found",
|
|
599
602
|
"investigate.card.bimi.pemErrors.cert-not-url_md": "**[](VMC#:glossary)** Certificate is not an url",
|
|
600
603
|
"investigate.card.bimi.pemErrors.cert-not-file_md": "**[](VMC#:glossary)** Certificate is not a file",
|
|
601
|
-
"investigate.card.bimi.pemErrors.cert-not-https_md": "**[](VMC#:glossary)** Certificate
|
|
604
|
+
"investigate.card.bimi.pemErrors.cert-not-https_md": "**[](VMC#:glossary)** Certificate does not use the HTTPS protocol",
|
|
602
605
|
"investigate.card.bimi.pemErrors.cert-not-pem_md": "**[](VMC#:glossary)** Certificate is not a PEM file",
|
|
603
606
|
"investigate.card.bimi.pemErrors.cert-not-valid_md": "**[](VMC#:glossary)** Certificate is not valid",
|
|
604
607
|
"investigate.card.bimi.pemErrors.cert-bad-date_md": "**[](VMC#:glossary)** Certificate has expired",
|
|
@@ -704,6 +707,7 @@ var enUS = {
|
|
|
704
707
|
"It is a protocol that was built to enforce **the existing SPF and DKIM protocols**."
|
|
705
708
|
],
|
|
706
709
|
"investigate.signal-description.DMARC_DOMAIN_md_LONG": [
|
|
710
|
+
"",
|
|
707
711
|
"DMARC does a few things:",
|
|
708
712
|
"",
|
|
709
713
|
"1. It takes into account the results from SPF and DKIM.",
|
|
@@ -718,6 +722,7 @@ var enUS = {
|
|
|
718
722
|
"It is a protocol that was built to enforce **the existing SPF and DKIM protocols**."
|
|
719
723
|
],
|
|
720
724
|
"investigate.signal-description.DMARC_md_LONG": [
|
|
725
|
+
"",
|
|
721
726
|
"DMARC does a few things:",
|
|
722
727
|
"",
|
|
723
728
|
"1. It takes into account the results from SPF and DKIM.",
|
|
@@ -728,6 +733,7 @@ var enUS = {
|
|
|
728
733
|
"investigate.signal-description.DMARC_md_INTRO": null,
|
|
729
734
|
"investigate.signal-description.DKIM_md_SHORT": "**DKIM** stands for *DomainKeys Identified Mail*. It is used to sign different header fields and the body of an email in order to authenticate the sending domain and prevent message modification during transit.",
|
|
730
735
|
"investigate.signal-description.DKIM_md_LONG": [
|
|
736
|
+
"",
|
|
731
737
|
"It achieves this by using **asymmetric cryptography** which consists of public and private keys. The private key is private to the sender’s domain and used to sign the emails. The public key is published in the sender’s DNS so it can be retrieved by anyone receiving messages from the sender.",
|
|
732
738
|
"",
|
|
733
739
|
"In essence, when an email is composed, its headers and body are signed using the private key of the sender to create a digital signature, which is also sent as a header field along with the email. On the receiver’s side (if DKIM enabled), the server retrieves the public key and verifies if the email was indeed signed by the sending domain. If the signature is successfully validated that proves that the sending domain sent the message and also that the headers and body of the message have not been modified during transmission."
|
|
@@ -735,11 +741,13 @@ var enUS = {
|
|
|
735
741
|
"investigate.signal-description.DKIM_md_INTRO": null,
|
|
736
742
|
"investigate.signal-description.TLS_md_SHORT": "TLS stands for **Transport Layer Security** and it is a protocol which helps **protect your emails by encrypting the connection** from the sender to recipient (client to server). Encryption makes snooping on your emails much harder while they travel on their way to your recipients. Encryption in transit is important so that your emails are read only by the intended recipients and not on their way there.",
|
|
737
743
|
"investigate.signal-description.TLS_md_LONG": [
|
|
744
|
+
"",
|
|
738
745
|
"Without using TLS your emails are exposed to snooping which means that they can be read by your internet provider or people on your network. Using TLS ensures that your emails are only read by the intended recipients. Please contact your service provider or administrator to enable TLS."
|
|
739
746
|
],
|
|
740
747
|
"investigate.signal-description.TLS_md_INTRO": null,
|
|
741
748
|
"investigate.signal-description.FCRDNS_md_SHORT": "**Forward-confirmed reverse DNS** (FCrDNS) is a spam filtering mechanism that tests if a given IP address has both **forward (name-to-address) and reverse (address-to-name)** Domain Name System (DNS) entries that match each other.",
|
|
742
749
|
"investigate.signal-description.FCRDNS_md_LONG": [
|
|
750
|
+
"",
|
|
743
751
|
"This verification is a weak form of authentication that exists to prove that there is a **valid relationship** between the owner of a domain name and the owner of the network that has been given an IP address. As this is difficult for spammers and spoofers to bypass FCrDNS is checked by some mail receivers in an effort to reduce phishing attacks and spam.",
|
|
744
752
|
"",
|
|
745
753
|
"Legitimate email servers should be correctly configured for FCrDNS to avoid deliverability issues."
|
|
@@ -759,29 +767,32 @@ var enUS = {
|
|
|
759
767
|
"investigate.signal-description.SUBDO_DOMAIN_ANALYZER_md": "We've checked your SPF record and haven't found any compromised \"includes\"",
|
|
760
768
|
"investigate.signal-description.SPF_md_SHORT": "SPF stands for **Sender Policy Framework**. It was developed to combat sender address forgery. It is an authentication protocol which **verifies the `MAIL FROM` or `HELO/EHLO` identities during email transmission**.",
|
|
761
769
|
"investigate.signal-description.SPF_md_LONG": [
|
|
770
|
+
"",
|
|
762
771
|
"SPF does this by comparing the sending server's IP address to a **list of authorized senders**. The authorized senders are the IP addresses which are allowed to send on behalf of the sending domain. They are **specified in a TXT record** which is published in the domain owner's DNS.",
|
|
763
772
|
"",
|
|
764
773
|
"If the receiving end supports SPF, then, upon receipt of an email it checks if the sending IP address is authorized to send on behalf of the domain and if is not in that list SPF authentication will fail.",
|
|
765
774
|
"",
|
|
766
|
-
"DMARC uses both SPF and DKIM. For information on what DKIM is please click
|
|
775
|
+
"DMARC uses both SPF and DKIM. For information on what DKIM is please [click here](https://knowledge.ondmarc.redsift.com/en/articles/1142653-what-is-dkim)."
|
|
767
776
|
],
|
|
768
777
|
"investigate.signal-description.SPF_md_INTRO": null,
|
|
769
778
|
"investigate.signal-description.SPF_DOMAIN_md_SHORT": "SPF stands for **Sender Policy Framework**. It was developed to combat sender address forgery. It is an authentication protocol which **verifies the `MAIL FROM` or `HELO/EHLO` identities during email transmission**.",
|
|
770
779
|
"investigate.signal-description.SPF_DOMAIN_md_LONG": [
|
|
780
|
+
"",
|
|
771
781
|
"SPF does this by comparing the sending server's IP address to a **list of authorized senders**. The authorized senders are the IP addresses which are allowed to send on behalf of the sending domain. They are **specified in a TXT record** which is published in the domain owner's DNS.",
|
|
772
782
|
"",
|
|
773
783
|
"If the receiving end supports SPF, then, upon receipt of an email it checks if the sending IP address is authorized to send on behalf of the domain and if is not in that list SPF authentication will fail.",
|
|
774
784
|
"",
|
|
775
|
-
"DMARC uses both SPF and DKIM. For information on what DKIM is please click
|
|
785
|
+
"DMARC uses both SPF and DKIM. For information on what DKIM is please [click here](https://knowledge.ondmarc.redsift.com/en/articles/1142653-what-is-dkim)."
|
|
776
786
|
],
|
|
777
787
|
"investigate.signal-description.SPF_DOMAIN_md_INTRO": null,
|
|
778
788
|
"investigate.signal-description.SPF_DOMAIN_ANALYZER_md_SHORT": "SPF stands for **Sender Policy Framework**. It was developed to combat sender address forgery. It is an authentication protocol which **verifies the `MAIL FROM` or `HELO/EHLO` identities during email transmission**.",
|
|
779
789
|
"investigate.signal-description.SPF_DOMAIN_ANALYZER_md_LONG": [
|
|
790
|
+
"",
|
|
780
791
|
"SPF does this by comparing the sending server's IP address to a **list of authorized senders**. The authorized senders are the IP addresses which are allowed to send on behalf of the sending domain. They are **specified in a TXT record** which is published in the domain owner's DNS.",
|
|
781
792
|
"",
|
|
782
793
|
"If the receiving end supports SPF, then, upon receipt of an email it checks if the sending IP address is authorized to send on behalf of the domain and if is not in that list SPF authentication will fail.",
|
|
783
794
|
"",
|
|
784
|
-
"DMARC uses both SPF and DKIM. For information on what DKIM is please click
|
|
795
|
+
"DMARC uses both SPF and DKIM. For information on what DKIM is please [click here](https://knowledge.ondmarc.redsift.com/en/articles/1142653-what-is-dkim)."
|
|
785
796
|
],
|
|
786
797
|
"investigate.signal-description.SPF_DOMAIN_ANALYZER_md_INTRO": null,
|
|
787
798
|
"investigate.signal-description.URLS_md_SHORT": "Shows all URLs extracted from the email. This is useful if you need to subscribe via a link to the service you are testing.",
|
|
@@ -789,6 +800,7 @@ var enUS = {
|
|
|
789
800
|
"investigate.signal-description.URLS_md_INTRO": null,
|
|
790
801
|
"investigate.signal-description.THREATINV_md_SHORT": "The results of the **Threat Intelligence** check help to identify suspicious emails or ones that should be blocked. It also highlights **deliverability** issues from legit sources.",
|
|
791
802
|
"investigate.signal-description.THREATINV_md_LONG": [
|
|
803
|
+
"",
|
|
792
804
|
"The **Spamhaus** databases that are checked are **comprehensive** and effective **threat intelligence data sets**. They are **continuously updated** and maintained by the Spamhaus Project researchers."
|
|
793
805
|
],
|
|
794
806
|
"investigate.signal-description.THREATINV_md_INTRO": "**Sender IP** and **Domain** were checked against databases of known **spammers**, **malware** disseminators, **non mail transfer agents**, **botnet** resources, **phishers**, or **low-reputation** senders.",
|
|
@@ -796,16 +808,20 @@ var enUS = {
|
|
|
796
808
|
"investigate.signal-description.THREATINV_DOMAIN_ANALYZER_NO_THREATS_md": "Domain was checked against several of trusted spammers database, web-mail transfer agents, botnet resources, phishers, or Non-reputation source: No suspicious activity.",
|
|
797
809
|
"investigate.signal-description.THREATINV_DOMAIN_ANALYZER_md_SHORT": "The results of the **Threat Intelligence** check help to identify suspicious domains or ones that should be blocked. It also highlights **deliverability** issues from legit sources.",
|
|
798
810
|
"investigate.signal-description.THREATINV_DOMAIN_ANALYZER_md_LONG": [
|
|
811
|
+
"",
|
|
799
812
|
"The **Spamhaus** databases that are checked are **comprehensive** and effective **threat intelligence data sets**. They are **continuously updated** and maintained by the Spamhaus Project researchers."
|
|
800
813
|
],
|
|
801
814
|
"investigate.signal-description.THREATINV_DOMAIN_ANALYZER_md_INTRO": "**Domain** was checked against databases of known **spammers**, **malware** disseminators, **non mail transfer agents**, **botnet** resources, **phishers**, or **low-reputation** senders.",
|
|
802
815
|
"investigate.signal-description.BIMI_md_SHORT": "**OnDMARC** and the Red Sift team can get your brand **BIMI compliant**, including issuing a **VMC** or **CMC** through our partners. [Learn more](https://redsift.com/pulse-platform/ondmarc/bimi)",
|
|
803
816
|
"investigate.signal-description.BIMI_md_LONG": [
|
|
817
|
+
"",
|
|
804
818
|
"To become **BIMI compliant** the following criteria must be met:",
|
|
805
819
|
"",
|
|
806
820
|
"1. The sending domain must be **DMARC compliant**.",
|
|
807
821
|
"2. You must hold the **trademark or certified rights for the brand logo** you want displayed.",
|
|
808
|
-
"3. You should have a **valid VMC or CMC certificate** which proves you are authorised to use the logo and are in control of the sending domain."
|
|
822
|
+
"3. You should have a **valid VMC or CMC certificate** which proves you are authorised to use the logo and are in control of the sending domain.",
|
|
823
|
+
"",
|
|
824
|
+
"For more details on the differences between VMC and CMC, see our [BIMI guide](https://redsift.com/guides/bimi#key-differences-between-vmc-and-cmc)."
|
|
809
825
|
],
|
|
810
826
|
"investigate.signal-description.BIMI_md_INTRO": "**BIMI**, or **Brand Indicators** for **Message Identification**, is a proposed standard that lets you display your company or brand logo next to your authenticated email messages in your customers inbox. [Learn more](https://redsift.com/pulse-platform/ondmarc/bimi)",
|
|
811
827
|
"investigate.signal-description.DNSSEC_md_SHORT": "The Domain Name System Security Extensions (DNSSEC) is a feature of the Domain Name System (DNS) that authenticates responses to domain name lookups. It does not provide privacy protections for those lookups, but prevents attackers from manipulating or poisoning the responses to DNS requests.",
|
|
@@ -818,6 +834,7 @@ var enUS = {
|
|
|
818
834
|
],
|
|
819
835
|
"investigate.signal-description.MTA-STS_md_SHORT": "**MTA-STS** (Mail Transfer Agent Strict Transport Security) tells sending servers to only deliver mail to your domain when a TLS connection can be negotiated and the policy you published is valid.",
|
|
820
836
|
"investigate.signal-description.MTA-STS_md_LONG": [
|
|
837
|
+
"",
|
|
821
838
|
"To be protected by **MTA-STS** you must:",
|
|
822
839
|
"",
|
|
823
840
|
"1. Publish an **mta-sts TXT record** that advertises your policy.",
|
|
@@ -951,8 +968,8 @@ var enUS = {
|
|
|
951
968
|
"glossary.label.RETURN_PATH": "Return Path",
|
|
952
969
|
"glossary.label.RETURN_PATH.value": "Return Path",
|
|
953
970
|
"glossary.label.RETURN_PATH.link": "return-path",
|
|
954
|
-
"glossary.label.DMARC_POLICY": "
|
|
955
|
-
"glossary.label.DMARC_POLICY.value": "
|
|
971
|
+
"glossary.label.DMARC_POLICY": "DMARC Policy",
|
|
972
|
+
"glossary.label.DMARC_POLICY.value": "DMARC Policy",
|
|
956
973
|
"glossary.label.DMARC_POLICY.value_FULL": "DMARC Policy",
|
|
957
974
|
"glossary.label.DMARC_POLICY.value_REPORTED": "report",
|
|
958
975
|
"glossary.label.DMARC_POLICY.value_QUARANTINE": "quarantine",
|
|
@@ -1466,6 +1483,7 @@ var frFR = {
|
|
|
1466
1483
|
"investigate.card.bimi.record-passed_md": "**[](BIMI_RECORD#:glossary)** **Présent et conforme**",
|
|
1467
1484
|
"investigate.card.bimi.record-declination_md": "**[](BIMI_RECORD#:glossary)** Présenter et contenir une **déclaration valide de publication**",
|
|
1468
1485
|
"investigate.card.bimi.record-no-cert_md": "**[](BIMI_RECORD#:glossary)** **Certificat non trouvé**",
|
|
1486
|
+
"investigate.card.bimi.cert-forbidden_md": "Votre certificat semble être derrière un système de protection anti-bot. [En savoir plus et comment résoudre le problème](https://knowledge.ondmarc.redsift.com/en/articles/8047013-ondmarc-cannot-fetch-my-bimi-logo-or-certificate)",
|
|
1469
1487
|
"investigate.card.bimi.record-failed_md": "**[](BIMI_RECORD#:glossary)** **Présent** mais avec des erreurs",
|
|
1470
1488
|
"investigate.card.bimi.record-missing_md": "**[](BIMI_RECORD#:glossary)** **Missing.** [Learn how to fix it](https://community.redsift.com/s/article/000001130)",
|
|
1471
1489
|
"investigate.card.bimi.could-not-fetch_md": "Échec de la récupération de **[](BIMI_RECORD#:glossary)**",
|
|
@@ -1479,6 +1497,7 @@ var frFR = {
|
|
|
1479
1497
|
"investigate.card.bimi.vmc.expiry-date_md": "**Expire le:** {date} ({daysLeft} jours restants)",
|
|
1480
1498
|
"investigate.card.bimi.vmc.expired-date_md": "Expiré le {date}",
|
|
1481
1499
|
"investigate.card.bimi.vmc.trademarkAuthority_md": "**Autorité de la marque : {trademarkAuthority}**",
|
|
1500
|
+
"investigate.card.bimi.vmc.assertionMark_md": "**Marque d'assertion :** {assertionMark}",
|
|
1482
1501
|
"investigate.card.bimi.logoErrors.invalid-svg_md": "**[](VMC#:glossary)** SVG non valide. Le logo du certificat ne peut pas être converti en un SVG valide.",
|
|
1483
1502
|
"investigate.card.bimi.logoErrors.invalid-svg-version_md": "**[](VMC#:glossary)** Version SVG invalide. Devrait être **1.2**",
|
|
1484
1503
|
"investigate.card.bimi.logoErrors.invalid-svg-profile_md": "**[](VMC#:glossary)** Profil SVG invalide. Doit être **tiny-ps**",
|
|
@@ -1499,10 +1518,11 @@ var frFR = {
|
|
|
1499
1518
|
"investigate.card.bimi.logoErrors.logo-and-evidence-mismatch_md": "**[](VMC#:glossary)** Logo sur l'enregistrement et sur le certificat ne correspondent pas",
|
|
1500
1519
|
"investigate.card.bimi.logoErrors.logo-extract-error_md": "**[](VMC#:glossary)** Erreur lors de l'extraction du logo",
|
|
1501
1520
|
"investigate.card.bimi.logoErrors.unknown-svg-error_md": "**[](VMC#:glossary)** Erreur inconnue lors de la validation du SVG",
|
|
1521
|
+
"investigate.card.bimi.svg-error-fallback_md": "**[](VMC#:glossary)** {error}",
|
|
1502
1522
|
"investigate.card.bimi.pemErrors.cert-not-found_md": "**[](VMC#:glossary)** Certificat non trouvé",
|
|
1503
1523
|
"investigate.card.bimi.pemErrors.cert-not-url_md": "**[](VMC#:glossary)** Le certificat n'est pas une url",
|
|
1504
1524
|
"investigate.card.bimi.pemErrors.cert-not-file_md": "**[](VMC#:glossary)** Le certificat n'est pas un fichier",
|
|
1505
|
-
"investigate.card.bimi.pemErrors.cert-not-https_md": "**[](VMC#:glossary)** Le certificat n'
|
|
1525
|
+
"investigate.card.bimi.pemErrors.cert-not-https_md": "**[](VMC#:glossary)** Le certificat n'utilise pas le protocole HTTPS",
|
|
1506
1526
|
"investigate.card.bimi.pemErrors.cert-not-pem_md": "**[](VMC#:glossary)** Le certificat n'est pas un fichier PEM",
|
|
1507
1527
|
"investigate.card.bimi.pemErrors.cert-not-valid_md": "**[](VMC#:glossary)** Le certificat n'est pas valide",
|
|
1508
1528
|
"investigate.card.bimi.pemErrors.cert-bad-date_md": "**[](VMC#:glossary)** Le certificat a expiré",
|
|
@@ -1608,6 +1628,7 @@ var frFR = {
|
|
|
1608
1628
|
"Il s'agit d'un protocole qui a été conçu pour renforcer **les protocoles SPF et DKIM existants**."
|
|
1609
1629
|
],
|
|
1610
1630
|
"investigate.signal-description.DMARC_DOMAIN_md_LONG": [
|
|
1631
|
+
"",
|
|
1611
1632
|
"DMARC a plusieurs fonctions :",
|
|
1612
1633
|
"",
|
|
1613
1634
|
"1. Il prend en compte les résultats de SPF et DKIM.",
|
|
@@ -1622,6 +1643,7 @@ var frFR = {
|
|
|
1622
1643
|
"Il s'agit d'un protocole qui a été conçu pour renforcer **les protocoles SPF et DKIM existants**."
|
|
1623
1644
|
],
|
|
1624
1645
|
"investigate.signal-description.DMARC_md_LONG": [
|
|
1646
|
+
"",
|
|
1625
1647
|
"DMARC a plusieurs fonctions :",
|
|
1626
1648
|
"",
|
|
1627
1649
|
"1. Il prend en compte les résultats de SPF et DKIM.",
|
|
@@ -1632,6 +1654,7 @@ var frFR = {
|
|
|
1632
1654
|
"investigate.signal-description.DMARC_md_INTRO": null,
|
|
1633
1655
|
"investigate.signal-description.DKIM_md_SHORT": "**DKIM** signifie *DomainKeys Identified Mail*. Il est utilisé pour signer différents champs d'en-tête et le corps d'un courrier électronique afin d'authentifier le domaine d'envoi et d'empêcher la modification du message pendant le transit.",
|
|
1634
1656
|
"investigate.signal-description.DKIM_md_LONG": [
|
|
1657
|
+
"",
|
|
1635
1658
|
"Pour ce faire, il utilise la **cryptographie asymétrique** qui consiste en des clés publiques et privées. La clé privée est propre au domaine de l'expéditeur et est utilisée pour signer les courriels. La clé publique est publiée dans le DNS de l'expéditeur et peut donc être récupérée par toute personne recevant des messages de l'expéditeur.",
|
|
1636
1659
|
"",
|
|
1637
1660
|
"Essentiellement, lorsqu'un courriel est composé, ses en-têtes et son corps sont signés à l'aide de la clé privée de l'expéditeur pour créer une signature numérique, qui est également envoyée en tant que champ d'en-tête avec le courriel. Du côté du destinataire (si le DKIM est activé), le serveur récupère la clé publique et vérifie si le courriel a bien été signé par le domaine d'envoi. Si la signature est validée avec succès, cela prouve que le domaine d'envoi a envoyé le message et que les en-têtes et le corps du message n'ont pas été modifiés pendant la transmission."
|
|
@@ -1639,11 +1662,13 @@ var frFR = {
|
|
|
1639
1662
|
"investigate.signal-description.DKIM_md_INTRO": null,
|
|
1640
1663
|
"investigate.signal-description.TLS_md_SHORT": "TLS signifie **Transport Layer Security** et il s'agit d'un protocole qui aide à **protéger vos courriels en chiffrant la connexion** entre l'expéditeur et le destinataire (du client au serveur). Le cryptage rend l'espionnage de vos courriels beaucoup plus difficile pendant leur acheminement vers vos destinataires. Le cryptage en transit est important pour que vos courriels ne soient lus que par les destinataires prévus et non en cours de route.",
|
|
1641
1664
|
"investigate.signal-description.TLS_md_LONG": [
|
|
1665
|
+
"",
|
|
1642
1666
|
"Sans l'utilisation de TLS, vos courriels sont exposés à l'espionnage, ce qui signifie qu'ils peuvent être lus par votre fournisseur d'accès à Internet ou par des personnes de votre réseau. L'utilisation de TLS garantit que vos courriels ne sont lus que par les destinataires prévus. Veuillez contacter votre fournisseur de services ou votre administrateur pour activer TLS."
|
|
1643
1667
|
],
|
|
1644
1668
|
"investigate.signal-description.TLS_md_INTRO": null,
|
|
1645
1669
|
"investigate.signal-description.FCRDNS_md_SHORT": "Le **Forward-confirmed reverse DNS** (FCrDNS) est un mécanisme de filtrage du spam qui teste si une adresse IP donnée possède à la fois des entrées **forward (nom vers adresse) et reverse (adresse vers nom)** du système de noms de domaine (DNS) qui correspondent l'une à l'autre.",
|
|
1646
1670
|
"investigate.signal-description.FCRDNS_md_LONG": [
|
|
1671
|
+
"",
|
|
1647
1672
|
"Cette vérification est une forme faible d'authentification qui existe pour prouver qu'il y a une **relation valide** entre le propriétaire d'un nom de domaine et le propriétaire du réseau qui a reçu une adresse IP. Comme il est difficile pour les spammeurs et les usurpateurs de contourner cette vérification, FCrDNS est vérifié par certains destinataires de courrier électronique dans le but de réduire les attaques par hameçonnage et le spam.",
|
|
1648
1673
|
"",
|
|
1649
1674
|
"Les serveurs de courrier électronique légitimes doivent être correctement configurés pour FCrDNS afin d'éviter les problèmes de délivrabilité."
|
|
@@ -1660,20 +1685,22 @@ var frFR = {
|
|
|
1660
1685
|
"investigate.signal-description.SUBDO_md": "Nous vérifions votre enregistrement SPF pour détecter les \"includes\" compromis qui pourraient laisser ce domaine ouvert aux attaques de spoofing.",
|
|
1661
1686
|
"investigate.signal-description.SPF_md_SHORT": "SPF signifie **Sender Policy Framework**. Il a été développé pour lutter contre la falsification de l'adresse de l'expéditeur. Il s'agit d'un protocole d'authentification qui **vérifie les identités `MAIL FROM` ou `HELO/EHLO` pendant la transmission du courrier électronique**.",
|
|
1662
1687
|
"investigate.signal-description.SPF_md_LONG": [
|
|
1688
|
+
"",
|
|
1663
1689
|
"Pour ce faire, SPF compare l'adresse IP du serveur d'envoi à une **liste d'expéditeurs autorisés**. Les expéditeurs autorisés sont les adresses IP qui sont autorisées à envoyer des messages au nom du domaine d'envoi. Elles sont **spécifiées dans un enregistrement TXT** qui est publié dans le DNS du propriétaire du domaine.",
|
|
1664
1690
|
"",
|
|
1665
1691
|
"Si le destinataire prend en charge SPF, il vérifie, lors de la réception d'un courrier électronique, si l'adresse IP d'envoi est autorisée à envoyer des messages au nom du domaine et, si elle ne figure pas dans cette liste, l'authentification SPF échoue.",
|
|
1666
1692
|
"",
|
|
1667
|
-
"DMARC utilise à la fois SPF et DKIM. Pour plus d'informations sur DKIM, cliquez
|
|
1693
|
+
"DMARC utilise à la fois SPF et DKIM. Pour plus d'informations sur DKIM, [cliquez ici](https://knowledge.ondmarc.redsift.com/en/articles/1142653-what-is-dkim)."
|
|
1668
1694
|
],
|
|
1669
1695
|
"investigate.signal-description.SPF_md_INTRO": "",
|
|
1670
1696
|
"investigate.signal-description.SPF_DOMAIN_md_SHORT": "SPF signifie **Sender Policy Framework**. Il a été développé pour lutter contre la falsification de l'adresse de l'expéditeur. Il s'agit d'un protocole d'authentification qui **vérifie les identités `MAIL FROM` ou `HELO/EHLO` pendant la transmission du courrier électronique**.",
|
|
1671
1697
|
"investigate.signal-description.SPF_DOMAIN_md_LONG": [
|
|
1698
|
+
"",
|
|
1672
1699
|
"Pour ce faire, SPF compare l'adresse IP du serveur d'envoi à une **liste d'expéditeurs autorisés**. Les expéditeurs autorisés sont les adresses IP qui sont autorisées à envoyer des messages au nom du domaine d'envoi. Elles sont **spécifiées dans un enregistrement TXT** qui est publié dans le DNS du propriétaire du domaine.",
|
|
1673
1700
|
"",
|
|
1674
1701
|
"Si le destinataire prend en charge SPF, il vérifie, lors de la réception d'un courrier électronique, si l'adresse IP d'envoi est autorisée à envoyer des messages au nom du domaine et, si elle ne figure pas dans cette liste, l'authentification SPF échoue.",
|
|
1675
1702
|
"",
|
|
1676
|
-
"DMARC utilise à la fois SPF et DKIM. Pour plus d'informations sur DKIM, cliquez
|
|
1703
|
+
"DMARC utilise à la fois SPF et DKIM. Pour plus d'informations sur DKIM, [cliquez ici](https://knowledge.ondmarc.redsift.com/en/articles/1142653-what-is-dkim)."
|
|
1677
1704
|
],
|
|
1678
1705
|
"investigate.signal-description.SPF_DOMAIN_md_INTRO": "",
|
|
1679
1706
|
"investigate.signal-description.SPF_DOMAIN_ANALYZER_md_SHORT": "SPF signifie **Sender Policy Framework**. Il a été développé pour lutter contre la falsification de l'adresse de l'expéditeur. Il s'agit d'un protocole d'authentification qui **vérifie les identités `MAIL FROM` ou `HELO/EHLO` pendant la transmission du courrier électronique**.",
|
|
@@ -1681,11 +1708,12 @@ var frFR = {
|
|
|
1681
1708
|
"investigate.signal-description.SUBDO_DOMAIN_ANALYZER_md_LONG": null,
|
|
1682
1709
|
"investigate.signal-description.SUBDO_DOMAIN_ANALYZER_md": "Nous avons vérifié votre enregistrement SPF et n'avons trouvé aucune inclusion compromise",
|
|
1683
1710
|
"investigate.signal-description.SPF_DOMAIN_ANALYZER_md_LONG": [
|
|
1711
|
+
"",
|
|
1684
1712
|
"Pour ce faire, SPF compare l'adresse IP du serveur d'envoi à une **liste d'expéditeurs autorisés**. Les expéditeurs autorisés sont les adresses IP qui sont autorisées à envoyer des messages au nom du domaine d'envoi. Elles sont **spécifiées dans un enregistrement TXT** qui est publié dans le DNS du propriétaire du domaine.",
|
|
1685
1713
|
"",
|
|
1686
1714
|
"Si le destinataire prend en charge SPF, il vérifie, lors de la réception d'un courrier électronique, si l'adresse IP d'envoi est autorisée à envoyer des messages au nom du domaine et, si elle ne figure pas dans cette liste, l'authentification SPF échoue.",
|
|
1687
1715
|
"",
|
|
1688
|
-
"DMARC utilise à la fois SPF et DKIM. Pour plus d'informations sur DKIM, cliquez
|
|
1716
|
+
"DMARC utilise à la fois SPF et DKIM. Pour plus d'informations sur DKIM, [cliquez ici](https://knowledge.ondmarc.redsift.com/en/articles/1142653-what-is-dkim)."
|
|
1689
1717
|
],
|
|
1690
1718
|
"investigate.signal-description.SPF_DOMAIN_ANALYZER_md_INTRO": "",
|
|
1691
1719
|
"investigate.signal-description.URLS_md_SHORT": "Affiche toutes les URL extraites de l'e-mail. Ceci est utile si vous avez besoin de vous abonner via un lien au service que vous testez.",
|
|
@@ -1693,6 +1721,7 @@ var frFR = {
|
|
|
1693
1721
|
"investigate.signal-description.URLS_md_INTRO": "",
|
|
1694
1722
|
"investigate.signal-description.THREATINV_md_SHORT": "Les résultats du contrôle **Threat Intelligence** permettent d'identifier les courriels suspects ou ceux qui devraient être bloqués. Ils mettent également en évidence les problèmes de **délivrabilité** provenant de sources légitimes.",
|
|
1695
1723
|
"investigate.signal-description.THREATINV_md_LONG": [
|
|
1724
|
+
"",
|
|
1696
1725
|
"Les bases de données **Spamhaus** qui sont vérifiées sont des **ensembles de données de renseignements sur les menaces** complets** et efficaces. Elles sont **mises à jour en permanence** et entretenues par les chercheurs du projet Spamhaus."
|
|
1697
1726
|
],
|
|
1698
1727
|
"investigate.signal-description.THREATINV_md_INTRO": "**L'IP** et le domaine** de l'expéditeur ont été comparés à des bases de données de **spammers**, **malwares**, **non mail transfer agents**, **botnet**, **phishers** ou **low-reputation** connus.",
|
|
@@ -1700,16 +1729,20 @@ var frFR = {
|
|
|
1700
1729
|
"investigate.signal-description.THREATINV_DOMAIN_ANALYZER_NO_THREATS_md": "Le domaine a été comparé à des bases de données de spammeurs, d'agents de transfert de courrier web, de botnets, de phishers et de sources non réputées de confiance : aucune activité suspecte.",
|
|
1701
1730
|
"investigate.signal-description.THREATINV_DOMAIN_ANALYZER_md_SHORT": "Les résultats du contrôle **Threat Intelligence** permettent d'identifier les domaines suspects ou ceux qui devraient être bloqués. Ils mettent également en évidence les problèmes de **délivrabilité** des sources légitimes.",
|
|
1702
1731
|
"investigate.signal-description.THREATINV_DOMAIN_ANALYZER_md_LONG": [
|
|
1732
|
+
"",
|
|
1703
1733
|
"Les bases de données **Spamhaus** qui sont vérifiées sont des **ensembles de données de renseignements sur les menaces** complets** et efficaces. Elles sont **mises à jour en permanence** et entretenues par les chercheurs du projet Spamhaus."
|
|
1704
1734
|
],
|
|
1705
1735
|
"investigate.signal-description.THREATINV_DOMAIN_ANALYZER_md_INTRO": "Le **domaine** a été comparé à des bases de données de **spammers**, **malwares**, **non mail transfer agents**, **botnet** resources, **phishers**, ou **low-reputation** senders connus.",
|
|
1706
1736
|
"investigate.signal-description.BIMI_md_SHORT": "**OnDMARC** et l'équipe de Red Sift peuvent faire en sorte que votre marque soit **conforme au BIMI**, y compris l'émission d'un **VMC** ou d'un **CMC** par l'intermédiaire de nos partenaires. [En savoir plus](https://redsift.com/pulse-platform/ondmarc/bimi)",
|
|
1707
1737
|
"investigate.signal-description.BIMI_md_LONG": [
|
|
1738
|
+
"",
|
|
1708
1739
|
"Pour devenir **conforme au BIMI**, les critères suivants doivent être remplis :",
|
|
1709
1740
|
"",
|
|
1710
1741
|
"1. Le domaine d'envoi doit être **DMARC compliant**.",
|
|
1711
1742
|
"2. Vous devez détenir la **marque ou des droits certifiés pour le logo** que vous souhaitez afficher.",
|
|
1712
|
-
"3. Vous devez disposer d'un **certificat VMC ou CMC valide** qui prouve que vous êtes autorisé à utiliser le logo et que vous contrôlez le domaine d'envoi."
|
|
1743
|
+
"3. Vous devez disposer d'un **certificat VMC ou CMC valide** qui prouve que vous êtes autorisé à utiliser le logo et que vous contrôlez le domaine d'envoi.",
|
|
1744
|
+
"",
|
|
1745
|
+
"Pour plus de détails sur les différences entre VMC et CMC, consultez notre [guide BIMI](https://redsift.com/guides/bimi#key-differences-between-vmc-and-cmc)."
|
|
1713
1746
|
],
|
|
1714
1747
|
"investigate.signal-description.BIMI_md_INTRO": "**BIMI**, ou **Brand Indicators** for **Message Identification**, est une proposition de norme qui vous permet d'afficher le logo de votre entreprise ou de votre marque à côté de vos messages électroniques authentifiés dans la boîte de réception de vos clients. [En savoir plus](https://redsift.com/pulse-platform/ondmarc/bimi)",
|
|
1715
1748
|
"investigate.signal-description.DNSSEC_md_SHORT": "Les extensions de sécurité du système de noms de domaine (DNSSEC) sont une fonctionnalité du système de noms de domaine (DNS) qui authentifie les réponses aux recherches de noms de domaine. Elle ne fournit pas de protection de la vie privée pour ces recherches, mais empêche les attaquants de manipuler ou d'empoisonner les réponses aux requêtes DNS.",
|
|
@@ -1722,6 +1755,7 @@ var frFR = {
|
|
|
1722
1755
|
],
|
|
1723
1756
|
"investigate.signal-description.MTA-STS_md_SHORT": "**MTA-STS** (Mail Transfer Agent Strict Transport Security) indique aux serveurs d'envoi de ne délivrer vos messages que lorsqu'une connexion TLS est négociée et que la politique que vous publiez est valide.",
|
|
1724
1757
|
"investigate.signal-description.MTA-STS_md_LONG": [
|
|
1758
|
+
"",
|
|
1725
1759
|
"Pour être protégé par **MTA-STS**, vous devez :",
|
|
1726
1760
|
"",
|
|
1727
1761
|
"1. Publier un **enregistrement TXT mta-sts** qui annonce votre politique.",
|
|
@@ -1851,8 +1885,8 @@ var frFR = {
|
|
|
1851
1885
|
"glossary.label.RETURN_PATH": "Return path",
|
|
1852
1886
|
"glossary.label.RETURN_PATH.value": "Return path",
|
|
1853
1887
|
"glossary.label.RETURN_PATH.link": "return-path",
|
|
1854
|
-
"glossary.label.DMARC_POLICY": "
|
|
1855
|
-
"glossary.label.DMARC_POLICY.value": "
|
|
1888
|
+
"glossary.label.DMARC_POLICY": "Politique DMARC",
|
|
1889
|
+
"glossary.label.DMARC_POLICY.value": "Politique DMARC",
|
|
1856
1890
|
"glossary.label.DMARC_POLICY.value_FULL": "Politique DMARC",
|
|
1857
1891
|
"glossary.label.DMARC_POLICY.value_REPORTED": "rapporté",
|
|
1858
1892
|
"glossary.label.DMARC_POLICY.value_QUARANTINE": "mis en quarantaine",
|
|
@@ -3346,44 +3380,64 @@ function getCardType$6() {
|
|
|
3346
3380
|
bimiRecordStatus = recordStatus.FAILED_TO_FETCH,
|
|
3347
3381
|
imageUrl,
|
|
3348
3382
|
svgErrors = [],
|
|
3349
|
-
vmc
|
|
3383
|
+
vmc,
|
|
3384
|
+
reportNew
|
|
3350
3385
|
} = bimi;
|
|
3351
3386
|
const svgValid = Boolean(imageUrl) && svgErrors.length === 0;
|
|
3387
|
+
|
|
3388
|
+
// Helper to get worst status from reportNew messages
|
|
3389
|
+
const getReportNewWorstStatus = () => {
|
|
3390
|
+
if (!reportNew || reportNew.length === 0) return null;
|
|
3391
|
+
const hasError = reportNew.some(r => r.status === 'error');
|
|
3392
|
+
const hasWarning = reportNew.some(r => r.status === 'warning');
|
|
3393
|
+
if (hasError) return CARD_STATUS$1.DANGER;
|
|
3394
|
+
if (hasWarning) return CARD_STATUS$1.WARNING;
|
|
3395
|
+
return null;
|
|
3396
|
+
};
|
|
3397
|
+
|
|
3398
|
+
// Helper to return the worst of two statuses
|
|
3399
|
+
const applyReportNewStatus = baseStatus => {
|
|
3400
|
+
const reportNewStatus = getReportNewWorstStatus();
|
|
3401
|
+
if (!reportNewStatus) return baseStatus;
|
|
3402
|
+
// DANGER is worse than WARNING is worse than GOOD
|
|
3403
|
+
if (reportNewStatus === CARD_STATUS$1.DANGER) return CARD_STATUS$1.DANGER;
|
|
3404
|
+
if (reportNewStatus === CARD_STATUS$1.WARNING && baseStatus === CARD_STATUS$1.GOOD) {
|
|
3405
|
+
return CARD_STATUS$1.WARNING;
|
|
3406
|
+
}
|
|
3407
|
+
return baseStatus;
|
|
3408
|
+
};
|
|
3352
3409
|
if (bimiRecordStatus === recordStatus.DECLINATION_TO_PUBLISH) {
|
|
3353
|
-
return CARD_STATUS$1.GOOD;
|
|
3410
|
+
return applyReportNewStatus(CARD_STATUS$1.GOOD);
|
|
3354
3411
|
}
|
|
3355
3412
|
|
|
3356
|
-
// Check
|
|
3357
|
-
|
|
3358
|
-
|
|
3413
|
+
// Check noRecordTxt first - this is a warning regardless of DMARC compliance
|
|
3414
|
+
// (matches legacy behavior from prod)
|
|
3415
|
+
if (bimiRecordStatus === recordStatus.NO_RECORD_TXT) {
|
|
3416
|
+
return applyReportNewStatus(CARD_STATUS$1.WARNING);
|
|
3359
3417
|
}
|
|
3360
3418
|
|
|
3361
|
-
//
|
|
3362
|
-
if (
|
|
3363
|
-
return CARD_STATUS$1.
|
|
3419
|
+
// Check DMARC compliance - if not compliant, it's danger
|
|
3420
|
+
if (!dmarcCompliant) {
|
|
3421
|
+
return applyReportNewStatus(CARD_STATUS$1.DANGER);
|
|
3364
3422
|
}
|
|
3365
|
-
if (bimiRecordStatus === recordStatus.FAILED_TO_FETCH || bimiRecordStatus === recordStatus.CERT_INVALID || bimiRecordStatus === recordStatus.NOT_VMC || bimiRecordStatus === recordStatus.WITH_ERRORS || bimiRecordStatus === recordStatus.CERT_NOT_FOUND || bimiRecordStatus === recordStatus.CERTIFICATE_FORBIDDEN) {
|
|
3366
|
-
return CARD_STATUS$1.DANGER;
|
|
3423
|
+
if (bimiRecordStatus === recordStatus.INVALID_RECORD_TXT || bimiRecordStatus === recordStatus.FAILED_TO_FETCH || bimiRecordStatus === recordStatus.CERT_INVALID || bimiRecordStatus === recordStatus.NOT_VMC || bimiRecordStatus === recordStatus.WITH_ERRORS || bimiRecordStatus === recordStatus.CERT_NOT_FOUND || bimiRecordStatus === recordStatus.CERTIFICATE_FORBIDDEN) {
|
|
3424
|
+
return applyReportNewStatus(CARD_STATUS$1.DANGER);
|
|
3367
3425
|
}
|
|
3368
3426
|
|
|
3369
|
-
// Check for expired VMC certificate
|
|
3427
|
+
// Check for expired VMC certificate - expired certs should be treated as danger
|
|
3370
3428
|
if (vmc !== null && vmc !== void 0 && vmc.expiryDate) {
|
|
3371
3429
|
const expiryDate = new Date(vmc.expiryDate);
|
|
3372
3430
|
const now = new Date();
|
|
3373
3431
|
if (expiryDate < now) {
|
|
3374
|
-
return CARD_STATUS$1.
|
|
3432
|
+
return applyReportNewStatus(CARD_STATUS$1.DANGER);
|
|
3375
3433
|
}
|
|
3376
3434
|
}
|
|
3377
3435
|
if (svgValid) {
|
|
3378
|
-
return CARD_STATUS$1.GOOD;
|
|
3436
|
+
return applyReportNewStatus(CARD_STATUS$1.GOOD);
|
|
3379
3437
|
}
|
|
3380
3438
|
|
|
3381
|
-
// SVG
|
|
3382
|
-
|
|
3383
|
-
if (svgErrors.length > 0) {
|
|
3384
|
-
return CARD_STATUS$1.WARNING;
|
|
3385
|
-
}
|
|
3386
|
-
return CARD_STATUS$1.DANGER;
|
|
3439
|
+
// SVG errors and missing images are danger conditions
|
|
3440
|
+
return applyReportNewStatus(CARD_STATUS$1.DANGER);
|
|
3387
3441
|
}
|
|
3388
3442
|
function extractDataUnsafe$9() {
|
|
3389
3443
|
let bimi = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
@@ -3854,7 +3908,7 @@ const StyledGlossaryTag = styled.a`
|
|
|
3854
3908
|
display: inline-flex;
|
|
3855
3909
|
align-items: center;
|
|
3856
3910
|
justify-content: center;
|
|
3857
|
-
padding:
|
|
3911
|
+
padding: 4px 8px;
|
|
3858
3912
|
margin: 0 0.35rem;
|
|
3859
3913
|
border-radius: 4px;
|
|
3860
3914
|
background-color: ${_ref => {
|
|
@@ -3869,6 +3923,7 @@ const StyledGlossaryTag = styled.a`
|
|
|
3869
3923
|
font-weight: 400;
|
|
3870
3924
|
font-family: var(--sc-font-body, ${DS_FONT_BODY$b});
|
|
3871
3925
|
white-space: nowrap;
|
|
3926
|
+
line-height: 1.3;
|
|
3872
3927
|
color: ${COLOR.grey.darkest} !important;
|
|
3873
3928
|
text-decoration: none !important;
|
|
3874
3929
|
transition: background-color 150ms ease;
|
|
@@ -4606,9 +4661,10 @@ const isValidUrl = url => {
|
|
|
4606
4661
|
*/
|
|
4607
4662
|
|
|
4608
4663
|
// Combined regex pattern for O(n) parsing - matches all markdown patterns in a single pass
|
|
4609
|
-
// Groups: 1=glossary text, 2=glossary term, 3=link text, 4=link url, 5=bold, 6=italic, 7=code
|
|
4664
|
+
// Groups: 1=glossary text, 2=glossary term, 3=http link text, 4=http link url, 5=bold, 6=italic, 7=code, 8=plain link text, 9=plain link value
|
|
4610
4665
|
// NOTE: Create new RegExp instance per call to avoid shared state issues with global flag
|
|
4611
|
-
|
|
4666
|
+
// Order matters: check glossary first, then http links, then plain links (most specific to least specific)
|
|
4667
|
+
const COMBINED_PATTERN_SOURCE = /\[([^\]]*)\]\(([A-Z_]+)#:glossary\)|\[([^\]]+)\]\((https?:\/\/[^)]+)\)|\*\*([^*]+)\*\*|\*(?!\*)([^*]+)\*(?!\*)|`([^`]+)`|\[([^\]]+)\]\(([^)]+)\)/.source;
|
|
4612
4668
|
function parseGlossaryMarkdown(text) {
|
|
4613
4669
|
if (!text || typeof text !== 'string') {
|
|
4614
4670
|
return text;
|
|
@@ -4711,6 +4767,13 @@ function parseGlossaryMarkdown(text) {
|
|
|
4711
4767
|
parts.push( /*#__PURE__*/React__default.createElement("code", {
|
|
4712
4768
|
key: `code-${keyCounter++}`
|
|
4713
4769
|
}, codeText));
|
|
4770
|
+
} else if (match[8] !== undefined && match[9] !== undefined) {
|
|
4771
|
+
// Plain link (non-http): [text](value) - render value as plain text
|
|
4772
|
+
// This handles cases like [svg-url](123) where 123 is not a valid URL
|
|
4773
|
+
const linkValue = match[9];
|
|
4774
|
+
parts.push( /*#__PURE__*/React__default.createElement("span", {
|
|
4775
|
+
key: `plain-link-${keyCounter++}`
|
|
4776
|
+
}, linkValue));
|
|
4714
4777
|
}
|
|
4715
4778
|
lastIndex = match.index + match[0].length;
|
|
4716
4779
|
}
|
|
@@ -5677,9 +5740,10 @@ const DescriptionToggle = styled.div`
|
|
|
5677
5740
|
*/
|
|
5678
5741
|
const CardWrapper = styled.div`
|
|
5679
5742
|
height: 100%;
|
|
5743
|
+
text-align: left;
|
|
5680
5744
|
|
|
5681
5745
|
@media only screen and (max-width: 768px) {
|
|
5682
|
-
min-width:
|
|
5746
|
+
min-width: auto;
|
|
5683
5747
|
}
|
|
5684
5748
|
|
|
5685
5749
|
/* Override DetailedCard header font (uses CSS var with DS fallback) */
|
|
@@ -6609,7 +6673,7 @@ const getIcon$1 = _ref5 => {
|
|
|
6609
6673
|
});
|
|
6610
6674
|
}
|
|
6611
6675
|
return /*#__PURE__*/React__default.createElement(Icon, {
|
|
6612
|
-
icon:
|
|
6676
|
+
icon: mdiInformationOutline,
|
|
6613
6677
|
size: "small"
|
|
6614
6678
|
});
|
|
6615
6679
|
case 'warning':
|
|
@@ -6641,7 +6705,8 @@ const InfoItem = _ref6 => {
|
|
|
6641
6705
|
subtexts,
|
|
6642
6706
|
hasWarning,
|
|
6643
6707
|
fluid,
|
|
6644
|
-
extractionBox
|
|
6708
|
+
extractionBox,
|
|
6709
|
+
'data-testid': dataTestId
|
|
6645
6710
|
} = _ref6;
|
|
6646
6711
|
const renderedText = renderValue(text, 'info-item-text');
|
|
6647
6712
|
const icon = getIcon$1({
|
|
@@ -6657,11 +6722,13 @@ const InfoItem = _ref6 => {
|
|
|
6657
6722
|
// Handle image type specially - render without flex wrapper to preserve overflow
|
|
6658
6723
|
if (type === 'image') {
|
|
6659
6724
|
return /*#__PURE__*/React__default.createElement(StyledInfoItem, {
|
|
6660
|
-
$fluid: fluid
|
|
6725
|
+
$fluid: fluid,
|
|
6726
|
+
"data-testid": dataTestId
|
|
6661
6727
|
}, renderedText.length ? renderedText : null);
|
|
6662
6728
|
}
|
|
6663
6729
|
const content = /*#__PURE__*/React__default.createElement(StyledInfoItem, {
|
|
6664
|
-
$fluid: fluid
|
|
6730
|
+
$fluid: fluid,
|
|
6731
|
+
"data-testid": dataTestId
|
|
6665
6732
|
}, /*#__PURE__*/React__default.createElement(StyledItemText, null, icon && /*#__PURE__*/React__default.createElement(StyledIconWrapper, null, icon), /*#__PURE__*/React__default.createElement(StyledContent, null, renderedText.length ? renderedText : null)), subtexts !== null && subtexts !== void 0 && subtexts.length ? /*#__PURE__*/React__default.createElement(StyledSubtexts, null, subtexts.map((subtext, idx) => /*#__PURE__*/React__default.createElement(React__default.Fragment, {
|
|
6666
6733
|
key: idx
|
|
6667
6734
|
}, renderValue(subtext.text, `info-item-subtext-${idx}`)))) : null);
|
|
@@ -7428,7 +7495,8 @@ const SignalCardNormal = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
7428
7495
|
key: `generic-${section.id}-${i}`,
|
|
7429
7496
|
header: section.title,
|
|
7430
7497
|
isCollapsible: (_section$isCollapsibl = section.isCollapsible) !== null && _section$isCollapsibl !== void 0 ? _section$isCollapsibl : false,
|
|
7431
|
-
isCollapsed: areAllCollapsed
|
|
7498
|
+
isCollapsed: areAllCollapsed,
|
|
7499
|
+
"data-testid": section.testId
|
|
7432
7500
|
}, section.content);
|
|
7433
7501
|
});
|
|
7434
7502
|
}, [sections, areAllCollapsed]);
|
|
@@ -7485,7 +7553,8 @@ const SignalCardNormal = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
7485
7553
|
key: genericSection.id,
|
|
7486
7554
|
header: genericSection.title,
|
|
7487
7555
|
isCollapsible: (_genericSection$isCol = genericSection.isCollapsible) !== null && _genericSection$isCol !== void 0 ? _genericSection$isCol : false,
|
|
7488
|
-
isCollapsed: areAllCollapsed
|
|
7556
|
+
isCollapsed: areAllCollapsed,
|
|
7557
|
+
"data-testid": genericSection.testId
|
|
7489
7558
|
}, genericSection.content)];
|
|
7490
7559
|
}
|
|
7491
7560
|
|
|
@@ -15199,7 +15268,7 @@ const LogosWrapper = styled.div`
|
|
|
15199
15268
|
display: flex;
|
|
15200
15269
|
flex-direction: row;
|
|
15201
15270
|
justify-content: flex-start;
|
|
15202
|
-
gap:
|
|
15271
|
+
gap: 16px;
|
|
15203
15272
|
}
|
|
15204
15273
|
|
|
15205
15274
|
border: 1px solid #dddddd;
|
|
@@ -15210,7 +15279,7 @@ const LogosWrapper = styled.div`
|
|
|
15210
15279
|
}
|
|
15211
15280
|
margin-bottom: 1.125rem;
|
|
15212
15281
|
max-width: 100%;
|
|
15213
|
-
overflow:
|
|
15282
|
+
overflow: hidden;
|
|
15214
15283
|
box-sizing: border-box;
|
|
15215
15284
|
|
|
15216
15285
|
background: ${_ref => {
|
|
@@ -15221,7 +15290,7 @@ const LogosWrapper = styled.div`
|
|
|
15221
15290
|
}};
|
|
15222
15291
|
|
|
15223
15292
|
& > :first-child {
|
|
15224
|
-
padding-right:
|
|
15293
|
+
padding-right: 8px;
|
|
15225
15294
|
@media only screen and (min-width: 768px) {
|
|
15226
15295
|
padding-right: 1.25rem;
|
|
15227
15296
|
}
|
|
@@ -15236,6 +15305,9 @@ const LogosWrapper = styled.div`
|
|
|
15236
15305
|
}
|
|
15237
15306
|
`;
|
|
15238
15307
|
const LogoElementWrapper = styled.div`
|
|
15308
|
+
flex-shrink: 1;
|
|
15309
|
+
min-width: 0;
|
|
15310
|
+
|
|
15239
15311
|
&,
|
|
15240
15312
|
& > div:first-child {
|
|
15241
15313
|
display: flex;
|
|
@@ -15256,6 +15328,7 @@ const LogoElementWrapper = styled.div`
|
|
|
15256
15328
|
background-size: cover;
|
|
15257
15329
|
background-repeat: no-repeat;
|
|
15258
15330
|
background-position: center;
|
|
15331
|
+
max-width: 100%;
|
|
15259
15332
|
|
|
15260
15333
|
${_ref2 => {
|
|
15261
15334
|
let {
|
|
@@ -15347,10 +15420,13 @@ const LogoElement = _ref8 => {
|
|
|
15347
15420
|
const [aspectRatio, setAspectRatio] = useState(`${size}x${size}`);
|
|
15348
15421
|
const [url, setUrl] = useState(svgUrl !== null && svgUrl !== void 0 ? svgUrl : isDark ? PLACEHOLDER_LIGHT : PLACEHOLDER_DARK);
|
|
15349
15422
|
const [error, setError] = useState(false);
|
|
15423
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
15350
15424
|
useEffect(() => {
|
|
15425
|
+
setIsLoaded(false);
|
|
15351
15426
|
if (!svgUrl) {
|
|
15352
15427
|
setUrl(isDark ? PLACEHOLDER_LIGHT : PLACEHOLDER_DARK);
|
|
15353
15428
|
setError(true);
|
|
15429
|
+
setIsLoaded(true);
|
|
15354
15430
|
return;
|
|
15355
15431
|
}
|
|
15356
15432
|
const img = new Image();
|
|
@@ -15360,6 +15436,7 @@ const LogoElement = _ref8 => {
|
|
|
15360
15436
|
height
|
|
15361
15437
|
} = img;
|
|
15362
15438
|
setAspectRatio(getAspectRatio(height, width));
|
|
15439
|
+
setIsLoaded(true);
|
|
15363
15440
|
};
|
|
15364
15441
|
img.onerror = error => {
|
|
15365
15442
|
componentLogger.error('Error loading image', error);
|
|
@@ -15369,6 +15446,7 @@ const LogoElement = _ref8 => {
|
|
|
15369
15446
|
}
|
|
15370
15447
|
setUrl(isDark ? PLACEHOLDER_LIGHT : PLACEHOLDER_DARK);
|
|
15371
15448
|
setError(true);
|
|
15449
|
+
setIsLoaded(true);
|
|
15372
15450
|
};
|
|
15373
15451
|
const newUrl = uncompressLogo(svgUrl);
|
|
15374
15452
|
img.src = newUrl;
|
|
@@ -15379,7 +15457,9 @@ const LogoElement = _ref8 => {
|
|
|
15379
15457
|
$square: square,
|
|
15380
15458
|
$size: size
|
|
15381
15459
|
}, /*#__PURE__*/React__default.createElement("div", null, /*#__PURE__*/React__default.createElement("div", {
|
|
15460
|
+
"data-testid": "bimi-logo-image",
|
|
15382
15461
|
"data-error": error,
|
|
15462
|
+
"data-loaded": isLoaded,
|
|
15383
15463
|
className: 'img',
|
|
15384
15464
|
style: {
|
|
15385
15465
|
backgroundImage: `url(${url})`
|
|
@@ -15498,7 +15578,9 @@ const BIMI_LINK = Object.freeze({
|
|
|
15498
15578
|
UNDERSTAND_ANALYZER: 'https://community.redsift.com/s/article/000001131',
|
|
15499
15579
|
LOGO_REQUIREMENTS: 'https://community.redsift.com/s/article/000001131',
|
|
15500
15580
|
HOW_TO_CREATE: 'https://blog.redsift.com/bimi/how-to-create-a-bimi-supported-svg-logo-file',
|
|
15501
|
-
CANNOT_FETCH_LOGO_OR_CERTIFICATE: 'https://knowledge.ondmarc.redsift.com/en/articles/8047013-ondmarc-cannot-fetch-my-bimi-logo-or-certificate'
|
|
15581
|
+
CANNOT_FETCH_LOGO_OR_CERTIFICATE: 'https://knowledge.ondmarc.redsift.com/en/articles/8047013-ondmarc-cannot-fetch-my-bimi-logo-or-certificate',
|
|
15582
|
+
WHAT_IS_BIMI: 'https://knowledge.ondmarc.redsift.com/en/articles/4124230-what-is-bimi',
|
|
15583
|
+
DMARC_POLICIES: 'https://knowledge.ondmarc.redsift.com/en/articles/2868231-what-are-the-different-dmarc-policies'
|
|
15502
15584
|
});
|
|
15503
15585
|
|
|
15504
15586
|
// ============================================================================
|
|
@@ -15578,34 +15660,44 @@ function getExtractedItemsDmarc(_ref2, t) {
|
|
|
15578
15660
|
fromDomain
|
|
15579
15661
|
} = dmarc;
|
|
15580
15662
|
if (policy) {
|
|
15581
|
-
|
|
15582
|
-
|
|
15583
|
-
|
|
15584
|
-
|
|
15585
|
-
|
|
15586
|
-
},
|
|
15587
|
-
items: [{
|
|
15663
|
+
const items = [];
|
|
15664
|
+
|
|
15665
|
+
// Only add fromDomain item if it has a valid value
|
|
15666
|
+
if (fromDomain) {
|
|
15667
|
+
items.push({
|
|
15588
15668
|
inline: true,
|
|
15589
15669
|
label: /*#__PURE__*/React__default.createElement(From, null),
|
|
15590
15670
|
text: fromDomain,
|
|
15591
15671
|
theme: 'email',
|
|
15592
15672
|
type: ''
|
|
15593
|
-
}
|
|
15594
|
-
|
|
15595
|
-
|
|
15596
|
-
|
|
15597
|
-
|
|
15598
|
-
|
|
15599
|
-
|
|
15600
|
-
|
|
15601
|
-
|
|
15602
|
-
|
|
15603
|
-
|
|
15673
|
+
});
|
|
15674
|
+
}
|
|
15675
|
+
items.push({
|
|
15676
|
+
label: /*#__PURE__*/React__default.createElement(DmarcPolicy, null),
|
|
15677
|
+
text: policy.p,
|
|
15678
|
+
theme: 'dns',
|
|
15679
|
+
type: ''
|
|
15680
|
+
}, {
|
|
15681
|
+
label: /*#__PURE__*/React__default.createElement(Pct, null),
|
|
15682
|
+
text: policy.pct,
|
|
15683
|
+
theme: 'dns',
|
|
15684
|
+
type: ''
|
|
15685
|
+
});
|
|
15686
|
+
if (policy.sp === 'none') {
|
|
15687
|
+
items.push({
|
|
15604
15688
|
label: /*#__PURE__*/React__default.createElement(Sp, null),
|
|
15605
15689
|
text: policy.sp,
|
|
15606
15690
|
theme: 'dns',
|
|
15607
15691
|
type: ''
|
|
15608
|
-
}
|
|
15692
|
+
});
|
|
15693
|
+
}
|
|
15694
|
+
extractedItemsCategories.push({
|
|
15695
|
+
title: t('section-titles.bimi-domain'),
|
|
15696
|
+
categoryType: 'dmarc-domain',
|
|
15697
|
+
extractionBox: {
|
|
15698
|
+
caption: 'dns'
|
|
15699
|
+
},
|
|
15700
|
+
items
|
|
15609
15701
|
});
|
|
15610
15702
|
}
|
|
15611
15703
|
return extractedItemsCategories;
|
|
@@ -15614,70 +15706,142 @@ function getExtractedItemsDmarc(_ref2, t) {
|
|
|
15614
15706
|
// ============================================================================
|
|
15615
15707
|
// Info Items Helpers
|
|
15616
15708
|
// ============================================================================
|
|
15617
|
-
|
|
15618
|
-
function getBimiItems(bimiRecordStatus, recordValidationErrors, t) {
|
|
15709
|
+
function getBimiItems(bimiRecordStatus, recordValidationErrors, reportNew, bimiRecordErrors, t) {
|
|
15619
15710
|
const items = [];
|
|
15620
|
-
|
|
15711
|
+
// Filter out 'bimi-error-invalid-record' when status is INVALID_RECORD_TXT to avoid duplicate messages
|
|
15712
|
+
const validationErrors = (recordValidationErrors !== null && recordValidationErrors !== void 0 ? recordValidationErrors : []).filter(errorCode => {
|
|
15713
|
+
if (bimiRecordStatus === recordStatus.INVALID_RECORD_TXT && errorCode === 'bimi-error-invalid-record') {
|
|
15714
|
+
return false;
|
|
15715
|
+
}
|
|
15716
|
+
return true;
|
|
15717
|
+
});
|
|
15621
15718
|
switch (bimiRecordStatus) {
|
|
15622
15719
|
case recordStatus.DECLINATION_TO_PUBLISH:
|
|
15623
15720
|
items.push({
|
|
15624
15721
|
text: t('card.bimi.record-declination_md'),
|
|
15625
|
-
type: 'good'
|
|
15722
|
+
type: 'good',
|
|
15723
|
+
'data-testid': 'bimi-record-declination'
|
|
15626
15724
|
});
|
|
15627
15725
|
break;
|
|
15628
15726
|
case recordStatus.VALID:
|
|
15629
15727
|
items.push({
|
|
15630
15728
|
text: t('card.bimi.record-passed_md'),
|
|
15631
|
-
type: 'good'
|
|
15729
|
+
type: 'good',
|
|
15730
|
+
'data-testid': 'bimi-record-valid'
|
|
15632
15731
|
});
|
|
15633
15732
|
break;
|
|
15634
15733
|
case recordStatus.INVALID_RECORD_TXT:
|
|
15635
15734
|
items.push({
|
|
15636
15735
|
text: t('card.bimi.record-invalid_md'),
|
|
15637
|
-
type: 'danger'
|
|
15736
|
+
type: 'danger',
|
|
15737
|
+
'data-testid': 'bimi-record-invalid'
|
|
15638
15738
|
});
|
|
15639
15739
|
validationErrors.forEach(errorCode => {
|
|
15640
15740
|
items.push({
|
|
15641
15741
|
text: t(`card.bimi.errors.${errorCode}`),
|
|
15642
|
-
type: '',
|
|
15643
|
-
theme: '
|
|
15742
|
+
type: 'info',
|
|
15743
|
+
theme: ''
|
|
15644
15744
|
});
|
|
15645
15745
|
});
|
|
15646
15746
|
break;
|
|
15647
15747
|
case recordStatus.CERT_NOT_FOUND:
|
|
15648
15748
|
items.push({
|
|
15649
15749
|
text: t('card.bimi.record-no-cert_md'),
|
|
15650
|
-
type: 'danger'
|
|
15750
|
+
type: 'danger',
|
|
15751
|
+
'data-testid': 'bimi-record-no-cert'
|
|
15651
15752
|
});
|
|
15652
15753
|
break;
|
|
15653
15754
|
case recordStatus.NOT_VMC:
|
|
15654
|
-
case recordStatus.CERT_INVALID:
|
|
15655
15755
|
case recordStatus.WITH_ERRORS:
|
|
15656
15756
|
items.push({
|
|
15657
15757
|
text: t('card.bimi.record-failed_md'),
|
|
15658
|
-
type: '
|
|
15758
|
+
type: 'warning',
|
|
15759
|
+
'data-testid': 'bimi-record-failed'
|
|
15760
|
+
});
|
|
15761
|
+
validationErrors.forEach(errorCode => {
|
|
15762
|
+
items.push({
|
|
15763
|
+
text: t(`card.bimi.errors.${errorCode}`),
|
|
15764
|
+
type: 'info',
|
|
15765
|
+
theme: ''
|
|
15766
|
+
});
|
|
15767
|
+
});
|
|
15768
|
+
break;
|
|
15769
|
+
case recordStatus.CERT_INVALID:
|
|
15770
|
+
items.push({
|
|
15771
|
+
text: t('card.bimi.record-failed_md'),
|
|
15772
|
+
type: 'warning',
|
|
15773
|
+
'data-testid': 'bimi-record-cert-invalid'
|
|
15659
15774
|
});
|
|
15660
15775
|
validationErrors.forEach(errorCode => {
|
|
15661
15776
|
items.push({
|
|
15662
15777
|
text: t(`card.bimi.errors.${errorCode}`),
|
|
15663
|
-
type: '',
|
|
15664
|
-
theme: '
|
|
15778
|
+
type: 'info',
|
|
15779
|
+
theme: ''
|
|
15665
15780
|
});
|
|
15666
15781
|
});
|
|
15667
15782
|
break;
|
|
15783
|
+
case recordStatus.CERTIFICATE_FORBIDDEN:
|
|
15784
|
+
items.push({
|
|
15785
|
+
text: t('card.bimi.cert-forbidden_md'),
|
|
15786
|
+
type: 'danger',
|
|
15787
|
+
'data-testid': 'bimi-record-cert-forbidden'
|
|
15788
|
+
});
|
|
15789
|
+
break;
|
|
15668
15790
|
case recordStatus.FAILED_TO_FETCH:
|
|
15669
15791
|
items.push({
|
|
15670
15792
|
text: t('card.bimi.could-not-fetch_md'),
|
|
15671
|
-
type: 'danger'
|
|
15793
|
+
type: 'danger',
|
|
15794
|
+
'data-testid': 'bimi-record-fetch-failed'
|
|
15672
15795
|
});
|
|
15673
15796
|
break;
|
|
15674
15797
|
case recordStatus.NO_RECORD_TXT:
|
|
15675
15798
|
default:
|
|
15676
15799
|
items.push({
|
|
15677
15800
|
text: t('card.bimi.record-missing_md'),
|
|
15678
|
-
type: 'danger'
|
|
15801
|
+
type: 'danger',
|
|
15802
|
+
'data-testid': 'bimi-record-not-found'
|
|
15679
15803
|
});
|
|
15680
15804
|
}
|
|
15805
|
+
|
|
15806
|
+
// Add reportNew messages if present, filtering out duplicates
|
|
15807
|
+
if (reportNew && reportNew.length > 0) {
|
|
15808
|
+
reportNew.forEach(report => {
|
|
15809
|
+
var _report$message;
|
|
15810
|
+
// Handle both camelCase (msgCode) and snake_case (msg_code) from API
|
|
15811
|
+
const msgCode = report.msgCode || report.msg_code;
|
|
15812
|
+
|
|
15813
|
+
// Skip "No BIMI record found" (DNS-BIMI-0008) when bimiRecordStatus already shows missing record
|
|
15814
|
+
if (msgCode === 'DNS-BIMI-0008' && bimiRecordStatus === recordStatus.NO_RECORD_TXT) {
|
|
15815
|
+
return;
|
|
15816
|
+
}
|
|
15817
|
+
// Skip "Declination to publish" (DNS-BIMI-0013) when bimiRecordStatus already shows declination
|
|
15818
|
+
// Also match on message text as fallback in case msgCode is missing
|
|
15819
|
+
const isDeclinationMessage = msgCode === 'DNS-BIMI-0013' || ((_report$message = report.message) === null || _report$message === void 0 ? void 0 : _report$message.toLowerCase().includes('declination to publish'));
|
|
15820
|
+
if (isDeclinationMessage && bimiRecordStatus === recordStatus.DECLINATION_TO_PUBLISH) {
|
|
15821
|
+
return;
|
|
15822
|
+
}
|
|
15823
|
+
// Map API status to item type: error -> danger, warning -> warning, info -> info
|
|
15824
|
+
const itemType = report.status === 'error' ? 'danger' : report.status;
|
|
15825
|
+
items.push({
|
|
15826
|
+
text: report.message,
|
|
15827
|
+
type: itemType,
|
|
15828
|
+
'data-testid': `bimi-report-${msgCode || report.status}`
|
|
15829
|
+
});
|
|
15830
|
+
});
|
|
15831
|
+
}
|
|
15832
|
+
|
|
15833
|
+
// Add bimiRecord.errors messages if present (specific validation errors like duplicate tags)
|
|
15834
|
+
if (bimiRecordErrors && bimiRecordErrors.length > 0) {
|
|
15835
|
+
bimiRecordErrors.forEach(error => {
|
|
15836
|
+
if (error.message) {
|
|
15837
|
+
items.push({
|
|
15838
|
+
text: error.message,
|
|
15839
|
+
type: 'danger',
|
|
15840
|
+
'data-testid': `bimi-record-error-${error.code || 'unknown'}`
|
|
15841
|
+
});
|
|
15842
|
+
}
|
|
15843
|
+
});
|
|
15844
|
+
}
|
|
15681
15845
|
return items;
|
|
15682
15846
|
}
|
|
15683
15847
|
function getInfoItemsCategoriesBimi() {
|
|
@@ -15685,11 +15849,14 @@ function getInfoItemsCategoriesBimi() {
|
|
|
15685
15849
|
let t = arguments.length > 1 ? arguments[1] : undefined;
|
|
15686
15850
|
const {
|
|
15687
15851
|
bimiRecordStatus = recordStatus.FAILED_TO_FETCH,
|
|
15688
|
-
recordValidationErrors
|
|
15852
|
+
recordValidationErrors,
|
|
15853
|
+
reportNew,
|
|
15854
|
+
bimiRecord
|
|
15689
15855
|
} = bimi;
|
|
15856
|
+
const bimiRecordErrors = bimiRecord === null || bimiRecord === void 0 ? void 0 : bimiRecord.errors;
|
|
15690
15857
|
return {
|
|
15691
15858
|
infoItemsCategories: [{
|
|
15692
|
-
items: getBimiItems(bimiRecordStatus, recordValidationErrors, t),
|
|
15859
|
+
items: getBimiItems(bimiRecordStatus, recordValidationErrors, reportNew, bimiRecordErrors, t),
|
|
15693
15860
|
title: t('card.bimi.record-status-title')
|
|
15694
15861
|
}]
|
|
15695
15862
|
};
|
|
@@ -15708,12 +15875,13 @@ function getInfoItemsCategoriesDmarc() {
|
|
|
15708
15875
|
}
|
|
15709
15876
|
const dmarcCompliantItems = [{
|
|
15710
15877
|
text: /*#__PURE__*/React__default.createElement(DmarcCompliant, null),
|
|
15711
|
-
type: dmarcCompliant ? 'good' : 'danger'
|
|
15878
|
+
type: dmarcCompliant ? 'good' : 'danger',
|
|
15879
|
+
'data-testid': `dmarc-compliance-${dmarcCompliant ? 'pass' : 'fail'}`
|
|
15712
15880
|
}];
|
|
15713
15881
|
if (!dmarcCompliant) {
|
|
15714
15882
|
dmarcCompliantItems.push({
|
|
15715
15883
|
text: parseGlossaryMarkdown(t('investigate:card.bimi.record-info_md')),
|
|
15716
|
-
type: '
|
|
15884
|
+
type: 'info',
|
|
15717
15885
|
theme: 'info'
|
|
15718
15886
|
});
|
|
15719
15887
|
}
|
|
@@ -15771,14 +15939,39 @@ function getSafeSVG() {
|
|
|
15771
15939
|
};
|
|
15772
15940
|
}
|
|
15773
15941
|
const items = [textItem, svgItem];
|
|
15774
|
-
|
|
15942
|
+
|
|
15943
|
+
// Only show svgErrors when imageUrl exists - if imageUrl is null, the "Logo missing" message is sufficient
|
|
15944
|
+
// Raw API errors like "can't fetch SVG from null: Get 'null': unsupported protocol scheme" are confusing
|
|
15945
|
+
if (!validSvg && imageAdded) {
|
|
15775
15946
|
svgErrors.forEach(msg => {
|
|
15776
|
-
const
|
|
15777
|
-
const
|
|
15778
|
-
|
|
15779
|
-
|
|
15780
|
-
|
|
15781
|
-
|
|
15947
|
+
const translationKey = `card.bimi.logoErrors.${msg}_md`;
|
|
15948
|
+
const translatedText = t(translationKey);
|
|
15949
|
+
|
|
15950
|
+
// Check if translation exists (key returned means no translation found)
|
|
15951
|
+
const hasTranslation = translatedText !== translationKey && !translatedText.endsWith('_md');
|
|
15952
|
+
if (hasTranslation) {
|
|
15953
|
+
// Known error with translation - use warning icon
|
|
15954
|
+
const errorText = localizeAssertionMarkdown(translatedText, assertionMarkType) || translatedText;
|
|
15955
|
+
items.push({
|
|
15956
|
+
text: errorText,
|
|
15957
|
+
type: 'warning'
|
|
15958
|
+
});
|
|
15959
|
+
} else {
|
|
15960
|
+
// Unknown error (e.g., "http status not OK") - use fallback message with outlined info icon
|
|
15961
|
+
// The API error may already include context, so just prefix with VMC glossary tag
|
|
15962
|
+
const fallbackText = t('card.bimi.svg-error-fallback_md', {
|
|
15963
|
+
error: msg
|
|
15964
|
+
});
|
|
15965
|
+
const errorText = localizeAssertionMarkdown(fallbackText, assertionMarkType) || fallbackText;
|
|
15966
|
+
// Pass as React element to prevent double-processing by Checklist's parseGlossaryMarkdown
|
|
15967
|
+
// Use type: 'info' with theme: '' to get the outlined info icon (mdiInformationOutline)
|
|
15968
|
+
// Empty string bypasses the default 'email' theme in Checklist.getIcon
|
|
15969
|
+
items.push({
|
|
15970
|
+
text: parseGlossaryMarkdown(errorText),
|
|
15971
|
+
type: 'info',
|
|
15972
|
+
theme: ''
|
|
15973
|
+
});
|
|
15974
|
+
}
|
|
15782
15975
|
});
|
|
15783
15976
|
}
|
|
15784
15977
|
return {
|
|
@@ -15800,10 +15993,20 @@ function getVMCCertificate() {
|
|
|
15800
15993
|
vmc,
|
|
15801
15994
|
pemUrl
|
|
15802
15995
|
} = bimi;
|
|
15803
|
-
|
|
15996
|
+
|
|
15997
|
+
// Validate pemUrl is a real URL - test placeholders like 'any-string-should-work' should not show VMC section
|
|
15998
|
+
const isValidPemUrl = pemUrl && (pemUrl.startsWith('http://') || pemUrl.startsWith('https://'));
|
|
15999
|
+
if (!vmc || !isValidPemUrl || bimiRecordStatus === recordStatus.FAILED_TO_FETCH || bimiRecordStatus === recordStatus.NO_RECORD_TXT) {
|
|
16000
|
+
return null;
|
|
16001
|
+
}
|
|
16002
|
+
|
|
16003
|
+
// Skip VMC section if pemUrl is actually a logo URL (ends with .svg)
|
|
16004
|
+
// This is a temporary hack - pemUrl shouldn't be populated when there's no a= tag
|
|
16005
|
+
if (pemUrl.endsWith('.svg')) {
|
|
15804
16006
|
return null;
|
|
15805
16007
|
}
|
|
15806
16008
|
const {
|
|
16009
|
+
assertionMark = null,
|
|
15807
16010
|
assertionMarkType: assertionMarkTypeRaw,
|
|
15808
16011
|
compliant = false,
|
|
15809
16012
|
expiryDate = null,
|
|
@@ -15824,7 +16027,17 @@ function getVMCCertificate() {
|
|
|
15824
16027
|
// Handle PEM errors
|
|
15825
16028
|
if (pemErrors.length > 0) {
|
|
15826
16029
|
pemErrors.forEach(error => {
|
|
15827
|
-
if (error === 'cert-
|
|
16030
|
+
if (error === 'cert-not-found') {
|
|
16031
|
+
// Show "Certificate not found" error
|
|
16032
|
+
const certNotFoundTextBase = t('card.bimi.pemErrors.cert-not-found_md');
|
|
16033
|
+
const certNotFoundText = localizeAssertionMarkdown(certNotFoundTextBase, assertionMarkType) || certNotFoundTextBase;
|
|
16034
|
+
vmcItems.items.push({
|
|
16035
|
+
text: certNotFoundText,
|
|
16036
|
+
type: 'danger',
|
|
16037
|
+
'data-testid': 'vmc-cert-not-found'
|
|
16038
|
+
});
|
|
16039
|
+
} else if (error === 'cert-forbidden') {
|
|
16040
|
+
// Show cert-forbidden which has special UI with a help link
|
|
15828
16041
|
vmcItems.items.push({
|
|
15829
16042
|
text: /*#__PURE__*/React__default.createElement(React__default.Fragment, null, t('certForbidden'), /*#__PURE__*/React__default.createElement(Link, {
|
|
15830
16043
|
href: BIMI_LINK.CANNOT_FETCH_LOGO_OR_CERTIFICATE,
|
|
@@ -15833,14 +16046,8 @@ function getVMCCertificate() {
|
|
|
15833
16046
|
}, t('certForbiddenLinkText'))),
|
|
15834
16047
|
type: 'danger'
|
|
15835
16048
|
});
|
|
15836
|
-
} else {
|
|
15837
|
-
const pemErrorTextBase = t(`card.bimi.pemErrors.${error}_md`);
|
|
15838
|
-
const pemErrorText = localizeAssertionMarkdown(pemErrorTextBase, assertionMarkType) || pemErrorTextBase;
|
|
15839
|
-
vmcItems.items.push({
|
|
15840
|
-
text: pemErrorText,
|
|
15841
|
-
type: 'danger'
|
|
15842
|
-
});
|
|
15843
16049
|
}
|
|
16050
|
+
// Skip other pemErrors - the compliance status "is invalid" provides this info with pem-url context
|
|
15844
16051
|
});
|
|
15845
16052
|
}
|
|
15846
16053
|
|
|
@@ -15859,15 +16066,16 @@ function getVMCCertificate() {
|
|
|
15859
16066
|
// Handle general errors (skip if error code is already in pemErrors or logoErrors)
|
|
15860
16067
|
const normalizedErrors = Array.isArray(errors) && errors.length ? errors.filter(error => typeof (error === null || error === void 0 ? void 0 : error.message) === 'string') : [];
|
|
15861
16068
|
|
|
15862
|
-
// Normalize
|
|
15863
|
-
const normalizedPemErrors = pemErrors.map(e => e.toLowerCase());
|
|
16069
|
+
// Normalize logoErrors for comparison
|
|
15864
16070
|
const normalizedLogoErrors = logoErrors.map(e => e.toLowerCase());
|
|
15865
|
-
|
|
16071
|
+
|
|
16072
|
+
// Only process general errors if no pemErrors exist (they contain duplicate/related messages)
|
|
16073
|
+
if (pemErrors.length === 0 && normalizedErrors.length > 0) {
|
|
15866
16074
|
normalizedErrors.forEach(error => {
|
|
15867
16075
|
var _error$code$toLowerCa, _error$code, _error$message;
|
|
15868
|
-
// Skip if this error code is already represented in
|
|
16076
|
+
// Skip if this error code is already represented in logoErrors
|
|
15869
16077
|
const errorCode = (_error$code$toLowerCa = error === null || error === void 0 ? void 0 : (_error$code = error.code) === null || _error$code === void 0 ? void 0 : _error$code.toLowerCase()) !== null && _error$code$toLowerCa !== void 0 ? _error$code$toLowerCa : '';
|
|
15870
|
-
if (errorCode &&
|
|
16078
|
+
if (errorCode && normalizedLogoErrors.includes(errorCode)) {
|
|
15871
16079
|
return;
|
|
15872
16080
|
}
|
|
15873
16081
|
const messageBase = (_error$message = error === null || error === void 0 ? void 0 : error.message) !== null && _error$message !== void 0 ? _error$message : '';
|
|
@@ -15896,12 +16104,14 @@ function getVMCCertificate() {
|
|
|
15896
16104
|
if (compliant) {
|
|
15897
16105
|
vmcItems.items.push({
|
|
15898
16106
|
text,
|
|
15899
|
-
type: 'good'
|
|
16107
|
+
type: 'good',
|
|
16108
|
+
'data-testid': 'vmc-validity-valid'
|
|
15900
16109
|
});
|
|
15901
16110
|
} else if (!pemErrors.find(err => err === 'cert-not-found')) {
|
|
15902
16111
|
vmcItems.items.push({
|
|
15903
16112
|
text,
|
|
15904
|
-
type: 'warning'
|
|
16113
|
+
type: pemErrors.length > 0 ? 'danger' : 'warning',
|
|
16114
|
+
'data-testid': 'vmc-validity-invalid'
|
|
15905
16115
|
});
|
|
15906
16116
|
}
|
|
15907
16117
|
|
|
@@ -15939,6 +16149,18 @@ function getVMCCertificate() {
|
|
|
15939
16149
|
});
|
|
15940
16150
|
}
|
|
15941
16151
|
|
|
16152
|
+
// Add assertion mark
|
|
16153
|
+
if (assertionMark) {
|
|
16154
|
+
const assertionMarkTextBase = t('card.bimi.vmc.assertionMark_md', {
|
|
16155
|
+
assertionMark
|
|
16156
|
+
});
|
|
16157
|
+
const assertionMarkText = localizeAssertionMarkdown(assertionMarkTextBase, assertionMarkType) || assertionMarkTextBase;
|
|
16158
|
+
vmcItems.items.push({
|
|
16159
|
+
text: assertionMarkText,
|
|
16160
|
+
type: 'no-icon'
|
|
16161
|
+
});
|
|
16162
|
+
}
|
|
16163
|
+
|
|
15942
16164
|
// Add trademark authority
|
|
15943
16165
|
if ((trademarkAuthority === null || trademarkAuthority === void 0 ? void 0 : trademarkAuthority.length) > 0) {
|
|
15944
16166
|
const trademarkTextBase = t('card.bimi.vmc.trademarkAuthority_md', {
|
|
@@ -15964,7 +16186,8 @@ function getVMCCertificate() {
|
|
|
15964
16186
|
vmcItems.items.push({
|
|
15965
16187
|
text: expiryText,
|
|
15966
16188
|
type: 'no-icon',
|
|
15967
|
-
theme: expired ? 'warn' : undefined
|
|
16189
|
+
theme: expired ? 'warn' : undefined,
|
|
16190
|
+
'data-testid': `vmc-expiration-${expired ? 'expired' : 'valid'}`
|
|
15968
16191
|
});
|
|
15969
16192
|
}
|
|
15970
16193
|
return vmcItems;
|
|
@@ -16060,7 +16283,8 @@ const SignalCardBimi$1 = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
16060
16283
|
title: cat.title,
|
|
16061
16284
|
content: /*#__PURE__*/React__default.createElement(Checklist$1, {
|
|
16062
16285
|
items: cat.items
|
|
16063
|
-
})
|
|
16286
|
+
}),
|
|
16287
|
+
testId: `bimi-dmarc-section-${i}`
|
|
16064
16288
|
}))) || []), ...((extractedItemsDmarc === null || extractedItemsDmarc === void 0 ? void 0 : extractedItemsDmarc.map((cat, i) => ({
|
|
16065
16289
|
id: `extractedItemsDmarc-${i}`,
|
|
16066
16290
|
title: cat.title,
|
|
@@ -16068,13 +16292,15 @@ const SignalCardBimi$1 = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
16068
16292
|
content: /*#__PURE__*/React__default.createElement(ExtractedCategoryContent, {
|
|
16069
16293
|
category: cat,
|
|
16070
16294
|
getTranslatedCaption: getTranslatedCaption
|
|
16071
|
-
})
|
|
16295
|
+
}),
|
|
16296
|
+
testId: `bimi-dmarc-extracted-${i}`
|
|
16072
16297
|
}))) || []), ...((infoItemsCategoriesBimi === null || infoItemsCategoriesBimi === void 0 ? void 0 : infoItemsCategoriesBimi.map((cat, i) => ({
|
|
16073
16298
|
id: `checklistsBimi-${i}`,
|
|
16074
16299
|
title: cat.title,
|
|
16075
16300
|
content: /*#__PURE__*/React__default.createElement(Checklist$1, {
|
|
16076
16301
|
items: cat.items
|
|
16077
|
-
})
|
|
16302
|
+
}),
|
|
16303
|
+
testId: `bimi-record-section-${i}`
|
|
16078
16304
|
}))) || []), ...((extractedItemsBimi === null || extractedItemsBimi === void 0 ? void 0 : extractedItemsBimi.map((cat, i) => ({
|
|
16079
16305
|
id: `extractedItemsBimi-${i}`,
|
|
16080
16306
|
title: cat.title,
|
|
@@ -16082,7 +16308,8 @@ const SignalCardBimi$1 = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
16082
16308
|
content: /*#__PURE__*/React__default.createElement(ExtractedCategoryContent, {
|
|
16083
16309
|
category: cat,
|
|
16084
16310
|
getTranslatedCaption: getTranslatedCaption
|
|
16085
|
-
})
|
|
16311
|
+
}),
|
|
16312
|
+
testId: `bimi-record-extracted-${i}`
|
|
16086
16313
|
}))) || [])];
|
|
16087
16314
|
if (VMCCertificate) {
|
|
16088
16315
|
sections.push({
|
|
@@ -16090,7 +16317,8 @@ const SignalCardBimi$1 = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
16090
16317
|
title: VMCCertificate.title,
|
|
16091
16318
|
content: /*#__PURE__*/React__default.createElement(Checklist$1, {
|
|
16092
16319
|
items: VMCCertificate.items
|
|
16093
|
-
})
|
|
16320
|
+
}),
|
|
16321
|
+
testId: 'bimi-vmc-section'
|
|
16094
16322
|
});
|
|
16095
16323
|
}
|
|
16096
16324
|
if (safeSVG) {
|
|
@@ -16099,14 +16327,14 @@ const SignalCardBimi$1 = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
16099
16327
|
title: safeSVG.title,
|
|
16100
16328
|
content: /*#__PURE__*/React__default.createElement(Checklist$1, {
|
|
16101
16329
|
items: safeSVG.items
|
|
16102
|
-
})
|
|
16330
|
+
}),
|
|
16331
|
+
testId: 'bimi-svg-section'
|
|
16103
16332
|
});
|
|
16104
16333
|
}
|
|
16105
16334
|
const sectionIds = sections.map(s => s.id);
|
|
16106
16335
|
|
|
16107
16336
|
// Generate summary items
|
|
16108
16337
|
const introDescriptionContent = t('signal-description.BIMI_md_INTRO', {
|
|
16109
|
-
context: 'Intro',
|
|
16110
16338
|
defaultValue: '',
|
|
16111
16339
|
returnObjects: true
|
|
16112
16340
|
});
|
|
@@ -16125,7 +16353,9 @@ const SignalCardBimi$1 = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
16125
16353
|
sections: sections,
|
|
16126
16354
|
isCollapsible: isCollapsible,
|
|
16127
16355
|
areAllCollapsed: areAllCollapsed,
|
|
16128
|
-
onCollapseAll: onCollapseAll
|
|
16356
|
+
onCollapseAll: onCollapseAll,
|
|
16357
|
+
"data-testid": "signal-card-bimi",
|
|
16358
|
+
"data-card-type": cardType
|
|
16129
16359
|
}, restProps));
|
|
16130
16360
|
} else {
|
|
16131
16361
|
return null;
|
|
@@ -20648,7 +20878,8 @@ const SignalCardDmarcDomain$1 = /*#__PURE__*/forwardRef(function SignalCardDmarc
|
|
|
20648
20878
|
title: cat.title,
|
|
20649
20879
|
content: /*#__PURE__*/React__default.createElement(Checklist$1, {
|
|
20650
20880
|
items: cat.items
|
|
20651
|
-
})
|
|
20881
|
+
}),
|
|
20882
|
+
testId: `dmarc-domain-section-${i}`
|
|
20652
20883
|
}))) || []), ...((extractedItemsCategories === null || extractedItemsCategories === void 0 ? void 0 : extractedItemsCategories.filter(cat => cat.items && cat.items.length > 0).map((cat, i) => {
|
|
20653
20884
|
var _cat$extractionBox;
|
|
20654
20885
|
return {
|
|
@@ -20659,7 +20890,8 @@ const SignalCardDmarcDomain$1 = /*#__PURE__*/forwardRef(function SignalCardDmarc
|
|
|
20659
20890
|
content: /*#__PURE__*/React__default.createElement(ExtractedCategoryContent, {
|
|
20660
20891
|
category: cat,
|
|
20661
20892
|
getTranslatedCaption: getTranslatedCaption
|
|
20662
|
-
})
|
|
20893
|
+
}),
|
|
20894
|
+
testId: `dmarc-domain-extracted-${i}`
|
|
20663
20895
|
};
|
|
20664
20896
|
})) || [])], [infoItemsCategories, extractedItemsCategories, useInvestigateColors, t]);
|
|
20665
20897
|
return /*#__PURE__*/React__default.createElement(SignalCardNormal, _extends({
|
|
@@ -20682,7 +20914,9 @@ const SignalCardDmarcDomain$1 = /*#__PURE__*/forwardRef(function SignalCardDmarc
|
|
|
20682
20914
|
bannerVariant: bannerVariant,
|
|
20683
20915
|
isCollapsible: resolvedIsCollapsible,
|
|
20684
20916
|
areAllCollapsed: resolvedAreAllCollapsed,
|
|
20685
|
-
onCollapseAll: handleCollapseAll
|
|
20917
|
+
onCollapseAll: handleCollapseAll,
|
|
20918
|
+
"data-testid": "signal-card-dmarc-domain",
|
|
20919
|
+
"data-card-type": cardType
|
|
20686
20920
|
}));
|
|
20687
20921
|
});
|
|
20688
20922
|
SignalCardDmarcDomain$1.className = CLASSNAME$c;
|
|
@@ -23242,6 +23476,7 @@ const _excluded$7 = ["useInvestigateColors", "isCollapsible", "areAllCollapsed",
|
|
|
23242
23476
|
const COMPONENT_NAME$7 = 'SignalCardSpf';
|
|
23243
23477
|
const CLASSNAME$7 = 'redsift-signal-card-spf';
|
|
23244
23478
|
const SignalCardSpf$1 = /*#__PURE__*/forwardRef((props, ref) => {
|
|
23479
|
+
var _jmap$extsecrep;
|
|
23245
23480
|
const {
|
|
23246
23481
|
useInvestigateColors,
|
|
23247
23482
|
isCollapsible,
|
|
@@ -23255,6 +23490,13 @@ const SignalCardSpf$1 = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
23255
23490
|
const {
|
|
23256
23491
|
t
|
|
23257
23492
|
} = useSignalCardTranslation('investigate');
|
|
23493
|
+
|
|
23494
|
+
// Build SPF Checker link if domain is available
|
|
23495
|
+
const spf = jmap === null || jmap === void 0 ? void 0 : (_jmap$extsecrep = jmap.extsecrep) === null || _jmap$extsecrep === void 0 ? void 0 : _jmap$extsecrep.spf;
|
|
23496
|
+
const domain = spf === null || spf === void 0 ? void 0 : spf.domain;
|
|
23497
|
+
const spfCheckerLink = domain && typeof domain === 'string' ? buildSPFCheckerLink(domain) : null;
|
|
23498
|
+
const ctaButtonName = t('card.subdo.button-name');
|
|
23499
|
+
const onCTAButtonClick = spfCheckerLink ? () => window.open(spfCheckerLink, '_blank') : undefined;
|
|
23258
23500
|
const computeInitialState = useMemo(() => {
|
|
23259
23501
|
const {
|
|
23260
23502
|
spf
|
|
@@ -23388,7 +23630,9 @@ const SignalCardSpf$1 = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
23388
23630
|
type: "SPF"
|
|
23389
23631
|
}, restProps, {
|
|
23390
23632
|
cardType: cardType !== null && cardType !== void 0 ? cardType : undefined,
|
|
23391
|
-
sections: sections
|
|
23633
|
+
sections: sections,
|
|
23634
|
+
ctaButtonName: ctaButtonName,
|
|
23635
|
+
onCTAButtonClick: onCTAButtonClick
|
|
23392
23636
|
}));
|
|
23393
23637
|
});
|
|
23394
23638
|
SignalCardSpf$1.className = CLASSNAME$7;
|
|
@@ -23405,7 +23649,7 @@ const STATUS = {
|
|
|
23405
23649
|
FAIL: 'fail'
|
|
23406
23650
|
};
|
|
23407
23651
|
|
|
23408
|
-
const _excluded$6 = ["className", "jmap", "onHeightChange", "bannerVariant", "useInvestigateColors"];
|
|
23652
|
+
const _excluded$6 = ["className", "jmap", "onHeightChange", "bannerVariant", "useInvestigateColors", "renderFooter"];
|
|
23409
23653
|
const COMPONENT_NAME$6 = 'SignalCardSpfDomain';
|
|
23410
23654
|
const CLASSNAME$6 = 'redsift-signal-card-spf-domain';
|
|
23411
23655
|
|
|
@@ -23422,21 +23666,75 @@ const getCardType$1 = status => {
|
|
|
23422
23666
|
|
|
23423
23667
|
/**
|
|
23424
23668
|
* Get SPF check result
|
|
23425
|
-
* Simple pass/fail message - matches legacy behavior
|
|
23669
|
+
* Simple pass/fail/warning message - matches legacy behavior
|
|
23426
23670
|
*/
|
|
23427
23671
|
const getSpfCheck = status => {
|
|
23428
23672
|
if (status === STATUS.PASS) {
|
|
23429
23673
|
return {
|
|
23430
23674
|
type: CARD_STATUS$1.GOOD,
|
|
23431
|
-
text:
|
|
23675
|
+
text: /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Spf, null), " authentication passed")
|
|
23676
|
+
};
|
|
23677
|
+
}
|
|
23678
|
+
if (status === 'warning') {
|
|
23679
|
+
return {
|
|
23680
|
+
type: CARD_STATUS$1.WARNING,
|
|
23681
|
+
text: /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Spf, null), " authentication detected problems")
|
|
23432
23682
|
};
|
|
23433
23683
|
}
|
|
23434
23684
|
return {
|
|
23435
23685
|
type: CARD_STATUS$1.DANGER,
|
|
23436
|
-
text:
|
|
23686
|
+
text: /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Spf, null), " authentication failed")
|
|
23437
23687
|
};
|
|
23438
23688
|
};
|
|
23439
23689
|
|
|
23690
|
+
/**
|
|
23691
|
+
* Get additional info items from the report array
|
|
23692
|
+
* Matches legacy extractDataDomainSpf behavior
|
|
23693
|
+
* Returns items with type='danger' for error messages from report
|
|
23694
|
+
*/
|
|
23695
|
+
const getReportItems = report => {
|
|
23696
|
+
if (!report || !Array.isArray(report)) {
|
|
23697
|
+
return [];
|
|
23698
|
+
}
|
|
23699
|
+
const items = [];
|
|
23700
|
+
report.forEach(item => {
|
|
23701
|
+
if (item.message === 'no-spf') {
|
|
23702
|
+
items.push({
|
|
23703
|
+
type: CARD_STATUS$1.DANGER,
|
|
23704
|
+
text: 'No SPF configured for the domain.'
|
|
23705
|
+
});
|
|
23706
|
+
} else if (item.message === 'ipf-error-spf') {
|
|
23707
|
+
var _item$spfError;
|
|
23708
|
+
const errorMessage = (_item$spfError = item.spfError) !== null && _item$spfError !== void 0 && _item$spfError.startsWith('dns-io') ? 'Temporary DNS error' : `SPF error: ${item.spfError}`;
|
|
23709
|
+
items.push({
|
|
23710
|
+
type: CARD_STATUS$1.DANGER,
|
|
23711
|
+
text: errorMessage
|
|
23712
|
+
});
|
|
23713
|
+
} else if (item.message === 'multiple-all') {
|
|
23714
|
+
items.push({
|
|
23715
|
+
type: CARD_STATUS$1.WARNING,
|
|
23716
|
+
text: 'Multiple all mechanisms detected.'
|
|
23717
|
+
});
|
|
23718
|
+
} else if (item.message === 'all-plus-warning') {
|
|
23719
|
+
items.push({
|
|
23720
|
+
type: CARD_STATUS$1.WARNING,
|
|
23721
|
+
text: 'All pass not recommended.'
|
|
23722
|
+
});
|
|
23723
|
+
} else if (item.message === 'all-not-last') {
|
|
23724
|
+
items.push({
|
|
23725
|
+
type: CARD_STATUS$1.WARNING,
|
|
23726
|
+
text: 'All not last detected.'
|
|
23727
|
+
});
|
|
23728
|
+
} else if (item.message === 'extra-spf-lookups') {
|
|
23729
|
+
items.push({
|
|
23730
|
+
type: CARD_STATUS$1.WARNING,
|
|
23731
|
+
text: 'Extra SPF lookups.'
|
|
23732
|
+
});
|
|
23733
|
+
}
|
|
23734
|
+
});
|
|
23735
|
+
return items;
|
|
23736
|
+
};
|
|
23737
|
+
|
|
23440
23738
|
/**
|
|
23441
23739
|
* SignalCardSpfDomain Component
|
|
23442
23740
|
*
|
|
@@ -23461,7 +23759,8 @@ const SignalCardSpfDomain$1 = /*#__PURE__*/forwardRef(function SignalCardSpfDoma
|
|
|
23461
23759
|
jmap,
|
|
23462
23760
|
onHeightChange,
|
|
23463
23761
|
bannerVariant,
|
|
23464
|
-
useInvestigateColors = false
|
|
23762
|
+
useInvestigateColors = false,
|
|
23763
|
+
renderFooter
|
|
23465
23764
|
} = props,
|
|
23466
23765
|
forwardedProps = _objectWithoutProperties(props, _excluded$6);
|
|
23467
23766
|
const {
|
|
@@ -23471,19 +23770,30 @@ const SignalCardSpfDomain$1 = /*#__PURE__*/forwardRef(function SignalCardSpfDoma
|
|
|
23471
23770
|
const {
|
|
23472
23771
|
raw,
|
|
23473
23772
|
status,
|
|
23474
|
-
txtExtractedFrom
|
|
23773
|
+
txtExtractedFrom,
|
|
23774
|
+
domain,
|
|
23775
|
+
report
|
|
23475
23776
|
} = spf || {};
|
|
23476
23777
|
|
|
23778
|
+
// Build SPF Checker link - use domain if available, fall back to txtExtractedFrom
|
|
23779
|
+
const spfDomain = domain || txtExtractedFrom;
|
|
23780
|
+
const spfCheckerLink = spfDomain && typeof spfDomain === 'string' ? buildSPFCheckerLink(spfDomain) : null;
|
|
23781
|
+
const ctaButtonName = t('card.subdo.button-name');
|
|
23782
|
+
const onCTAButtonClick = spfCheckerLink ? () => window.open(spfCheckerLink, '_blank') : undefined;
|
|
23783
|
+
|
|
23477
23784
|
// Handle both string and array formats for raw SPF record
|
|
23478
|
-
//
|
|
23479
|
-
const rawRecord = useMemo(() =>
|
|
23785
|
+
// Show "No SPF record found" for empty/missing records instead of "unknown"
|
|
23786
|
+
const rawRecord = useMemo(() => {
|
|
23787
|
+
if (Array.isArray(raw)) {
|
|
23788
|
+
return raw.length > 0 ? raw[0] : 'No SPF record found';
|
|
23789
|
+
}
|
|
23790
|
+
// Check for empty string, null, or undefined
|
|
23791
|
+
return raw && raw.trim() !== '' ? raw : 'No SPF record found';
|
|
23792
|
+
}, [raw]);
|
|
23480
23793
|
const cardType = useMemo(() => getCardType$1(status), [status]);
|
|
23481
23794
|
|
|
23482
|
-
//
|
|
23483
|
-
const
|
|
23484
|
-
title: 'SPF',
|
|
23485
|
-
items: [getSpfCheck(status)]
|
|
23486
|
-
}], [status]);
|
|
23795
|
+
// Build all checklist items: main status check + report items
|
|
23796
|
+
const checklistItems = useMemo(() => [getSpfCheck(status), ...getReportItems(report)], [status, report]);
|
|
23487
23797
|
|
|
23488
23798
|
// Simple extracted items - just show the SPF record with extraction box
|
|
23489
23799
|
const extractedItemsCategories = useMemo(() => [{
|
|
@@ -23520,21 +23830,27 @@ const SignalCardSpfDomain$1 = /*#__PURE__*/forwardRef(function SignalCardSpfDoma
|
|
|
23520
23830
|
if (!caption) return undefined;
|
|
23521
23831
|
return t(EXTRACTION_CAPTION_KEYS[caption]);
|
|
23522
23832
|
};
|
|
23523
|
-
const sections = useMemo(() => [
|
|
23833
|
+
const sections = useMemo(() => [
|
|
23834
|
+
// SPF Policy section with DNS record
|
|
23835
|
+
...extractedItemsCategories.filter(cat => cat.items && cat.items.length > 0).map((cat, i) => ({
|
|
23524
23836
|
id: `extractedItems-${i}`,
|
|
23525
23837
|
title: cat.title,
|
|
23526
23838
|
isCollapsible: true,
|
|
23527
23839
|
content: /*#__PURE__*/React__default.createElement(ExtractedCategoryContent, {
|
|
23528
23840
|
category: cat,
|
|
23529
23841
|
getTranslatedCaption: getTranslatedCaption
|
|
23530
|
-
})
|
|
23531
|
-
|
|
23532
|
-
|
|
23533
|
-
|
|
23842
|
+
}),
|
|
23843
|
+
testId: `spf-domain-extracted-${i}`
|
|
23844
|
+
})),
|
|
23845
|
+
// SPF status section with all checklist items (main status + report errors)
|
|
23846
|
+
{
|
|
23847
|
+
id: 'spf-status',
|
|
23848
|
+
title: 'SPF',
|
|
23534
23849
|
content: /*#__PURE__*/React__default.createElement(Checklist$1, {
|
|
23535
|
-
items:
|
|
23536
|
-
})
|
|
23537
|
-
|
|
23850
|
+
items: checklistItems
|
|
23851
|
+
}),
|
|
23852
|
+
testId: 'spf-domain-status-section'
|
|
23853
|
+
}], [extractedItemsCategories, checklistItems, t]);
|
|
23538
23854
|
if (!spf) return null;
|
|
23539
23855
|
return /*#__PURE__*/React__default.createElement(SignalCardNormal, _extends({
|
|
23540
23856
|
useInvestigateColors: useInvestigateColors
|
|
@@ -23546,9 +23862,20 @@ const SignalCardSpfDomain$1 = /*#__PURE__*/forwardRef(function SignalCardSpfDoma
|
|
|
23546
23862
|
onComponentMount: handleComponentMount,
|
|
23547
23863
|
sections: sections,
|
|
23548
23864
|
bannerVariant: bannerVariant,
|
|
23865
|
+
renderFooter: renderFooter,
|
|
23866
|
+
ctaButtonName: ctaButtonName,
|
|
23867
|
+
onCTAButtonClick: onCTAButtonClick,
|
|
23868
|
+
shortDescription: t('signal-description.SPF_DOMAIN_md_SHORT', {
|
|
23869
|
+
returnObjects: true
|
|
23870
|
+
}),
|
|
23871
|
+
longDescription: t('signal-description.SPF_DOMAIN_md_LONG', {
|
|
23872
|
+
returnObjects: true
|
|
23873
|
+
}),
|
|
23549
23874
|
isCollapsible: true,
|
|
23550
23875
|
areAllCollapsed: areAllCollapsed,
|
|
23551
|
-
onCollapseAll: handleCollapseAll
|
|
23876
|
+
onCollapseAll: handleCollapseAll,
|
|
23877
|
+
"data-testid": "signal-card-spf-domain",
|
|
23878
|
+
"data-card-type": cardType
|
|
23552
23879
|
}));
|
|
23553
23880
|
});
|
|
23554
23881
|
SignalCardSpfDomain$1.displayName = COMPONENT_NAME$6;
|
|
@@ -23759,6 +24086,11 @@ const SignalCardSpfDomainAnalyzer$1 = /*#__PURE__*/forwardRef(function SignalCar
|
|
|
23759
24086
|
} = spf || {};
|
|
23760
24087
|
const recordsArray = useMemo(() => Array.isArray(records) ? records : [], [records]);
|
|
23761
24088
|
const cardType = useMemo(() => getCardType(status), [status]);
|
|
24089
|
+
|
|
24090
|
+
// Build SPF Checker link if domain is available
|
|
24091
|
+
const spfCheckerLink = domain && typeof domain === 'string' ? buildSPFCheckerLink(domain) : null;
|
|
24092
|
+
const ctaButtonName = t('card.subdo.button-name');
|
|
24093
|
+
const onCTAButtonClick = spfCheckerLink ? () => window.open(spfCheckerLink, '_blank') : undefined;
|
|
23762
24094
|
const resolveT = useResolveTranslation(['investigate'], {
|
|
23763
24095
|
prefixes: ['card.spf.', 'card.spf.spf-']
|
|
23764
24096
|
});
|
|
@@ -23853,6 +24185,8 @@ const SignalCardSpfDomainAnalyzer$1 = /*#__PURE__*/forwardRef(function SignalCar
|
|
|
23853
24185
|
onHeightChange: onHeightChange,
|
|
23854
24186
|
bannerVariant: bannerVariant,
|
|
23855
24187
|
useInvestigateColors: useInvestigateColors,
|
|
24188
|
+
ctaButtonName: ctaButtonName,
|
|
24189
|
+
onCTAButtonClick: onCTAButtonClick,
|
|
23856
24190
|
shortDescription: t('signal-description.SPF_DOMAIN_ANALYZER_md_SHORT', {
|
|
23857
24191
|
returnObjects: true
|
|
23858
24192
|
}),
|