diff --git a/dev/Model/Email.js b/dev/Model/Email.js index c47738b2c..b17692f81 100644 --- a/dev/Model/Email.js +++ b/dev/Model/Email.js @@ -10,13 +10,15 @@ /** * @param {string=} sEmail * @param {string=} sName + * @param {string=} sDkimStatus * * @constructor */ - function EmailModel(sEmail, sName) + function EmailModel(sEmail, sName, sDkimStatus) { this.email = sEmail || ''; this.name = sName || ''; + this.dkimStatus = sDkimStatus || 'none'; this.clearDuplicateName(); } @@ -42,10 +44,16 @@ */ EmailModel.prototype.email = ''; + /** + * @type {string} + */ + EmailModel.prototype.dkimStatus = 'none'; + EmailModel.prototype.clear = function () { this.email = ''; this.name = ''; + this.dkimStatus = 'none'; }; /** @@ -121,6 +129,7 @@ { this.name = Utils.trim(oJsonEmail.Name); this.email = Utils.trim(oJsonEmail.Email); + this.dkimStatus = Utils.trim(oJsonEmail.DkimStatus || ''); bResult = '' !== this.email; this.clearDuplicateName(); diff --git a/dev/Model/Message.js b/dev/Model/Message.js index 49bfa31f4..e0bc148d4 100644 --- a/dev/Model/Message.js +++ b/dev/Model/Message.js @@ -563,6 +563,21 @@ return MessageModel.emailsToLine(this.from, bFriendlyView, bWrapWithLink); }; + /** + * @return {string} + */ + MessageModel.prototype.fromDkimData = function () + { + var aResult = ['none', '']; + if (Utils.isNonEmptyArray(this.from) && 1 === this.from.length && + this.from[0] && this.from[0].dkimStatus) + { + aResult = [this.from[0].dkimStatus, this.from[0].email]; + } + + return aResult; + }; + /** * @param {boolean} bFriendlyView * @param {boolean=} bWrapWithLink = false diff --git a/dev/Styles/_FontasticToBoot.less b/dev/Styles/_FontasticToBoot.less index 5415509d5..2a67de993 100644 --- a/dev/Styles/_FontasticToBoot.less +++ b/dev/Styles/_FontasticToBoot.less @@ -58,6 +58,26 @@ } } +.iconcolor-display-none { + display: none; +} + +.iconcolor-green { + color: green; +} + +.iconcolor-red { + color: red; +} + +.iconcolor-white { + color: white; +} + +.iconcolor-grey { + color: #aaa; +} + .denied-by-browser { cursor: default; .icon-checkbox-checked, icon-checkbox-unchecked { diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index 300564ea3..6402ca868 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -152,6 +152,7 @@ this.viewHash = ''; this.viewSubject = ko.observable(''); this.viewFromShort = ko.observable(''); + this.viewFromDkimData = ko.observable(['none', '']); this.viewToShort = ko.observable(''); this.viewFrom = ko.observable(''); this.viewTo = ko.observable(''); @@ -176,6 +177,33 @@ return this.message() ? this.message().pgpSignedVerifyUser() : ''; }, this); + this.viewFromDkimStatusIconClass = ko.computed(function () { + +// var sResult = 'icon-warning-alt iconcolor-grey'; + var sResult = 'icon-none iconcolor-display-none'; + switch (this.viewFromDkimData()[0]) + { + case 'none': +// sResult = 'icon-warning-alt iconcolor-grey'; + sResult = 'icon-none iconcolor-display-none'; + break; + case 'pass': + sResult = 'icon-ok iconcolor-green'; + break; + default: + sResult = 'icon-warning-alt iconcolor-red'; + break; + } + + return sResult; + + }, this); + + this.viewFromDkimStatusTitle = ko.computed(function () { + var aStatus = this.viewFromDkimData(); + return Utils.isNonEmptyArray(aStatus) ? 'DKIM: ' + aStatus[0] + ' (' + aStatus[1] + ')' : ''; + }, this); + this.message.subscribe(function (oMessage) { this.messageActiveDom(null); @@ -192,6 +220,7 @@ this.viewHash = oMessage.hash; this.viewSubject(oMessage.subject()); this.viewFromShort(oMessage.fromToLine(true, true)); + this.viewFromDkimData(oMessage.fromDkimData()); this.viewToShort(oMessage.toToLine(true, true)); this.viewFrom(oMessage.fromToLine(false)); this.viewTo(oMessage.toToLine(false)); diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/Message.php b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/Message.php index b6bc23c68..c2f9f71cd 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/Message.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/Message.php @@ -657,6 +657,8 @@ class Message $this->oCc = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::CC, $bCharsetAutoDetect); $this->oBcc = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::BCC, $bCharsetAutoDetect); + $oHeaders->PopulateEmailColectionByDkim($this->oFrom); + $this->oSender = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::SENDER, $bCharsetAutoDetect); $this->oReplyTo = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::REPLY_TO, $bCharsetAutoDetect); $this->oDeliveredTo = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::DELIVERED_TO, $bCharsetAutoDetect); diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Email.php b/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Email.php index 0fb51bde9..a1bd84c2d 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Email.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Email.php @@ -32,6 +32,11 @@ class Email */ private $sRemark; + /** + * @var string + */ + private $sDkimStatus; + /** * @access private * @@ -51,6 +56,8 @@ class Email $this->sEmail = \MailSo\Base\Utils::IdnToAscii(\trim($sEmail), true); $this->sDisplayName = \trim($sDisplayName); $this->sRemark = \trim($sRemark); + + $this->sDkimStatus = \MailSo\Mime\Enumerations\DkimStatus::NONE; } /** @@ -223,6 +230,14 @@ class Email return $this->sRemark; } + /** + * @return string + */ + public function GetDkimStatus() + { + return $this->sDkimStatus; + } + /** * @return string */ @@ -241,14 +256,22 @@ class Email return \MailSo\Base\Utils::GetDomainFromEmail($this->GetEmail($bIdn)); } + /** + * @param string $sDkimStatus + */ + public function SetDkimStatus($sDkimStatus) + { + $this->sDkimStatus = \MailSo\Mime\Enumerations\DkimStatus::normalizeValue($sDkimStatus); + } + /** * @param bool $bIdn = false - * + * * @return array */ public function ToArray($bIdn = false) { - return array($this->sDisplayName, $this->GetEmail($bIdn), $this->sRemark); + return array($this->sDisplayName, $this->GetEmail($bIdn), $this->sRemark, $this->sDkimStatus); } /** diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Enumerations/DkimStatus.php b/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Enumerations/DkimStatus.php new file mode 100644 index 000000000..1141bf4ba --- /dev/null +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Mime/Enumerations/DkimStatus.php @@ -0,0 +1,57 @@ +Add($oHeader); } - + $sName = null; $sValue = null; } @@ -355,6 +356,79 @@ class HeaderCollection extends \MailSo\Base\Collection return $this; } + /** + * @return int + */ + public function DkimStatuses() + { + $aResult = array(); + + $aHeaders = $this->ValuesByName(\MailSo\Mime\Enumerations\Header::AUTHENTICATION_RESULTS); + if (\is_array($aHeaders) && 0 < \count($aHeaders)) + { + foreach ($aHeaders as $sHeaderValue) + { + $sStatus = ''; + $sDomain = ''; + $sDkimLine = ''; + + $aMatch = array(); + + if (\preg_match('/dkim=[^\r\n;]+/i', $sHeaderValue, $aMatch) && !empty($aMatch[0])) + { + $sDkimLine = $aMatch[0]; + + $aMatch = array(); + if (\preg_match('/dkim=([a-zA-Z0-9]+)/i', $sDkimLine, $aMatch) && !empty($aMatch[1])) + { + $sStatus = $aMatch[1]; + } + + $aMatch = array(); + if (\preg_match('/header\.(d|i|from)=([^\s]+)/i', $sDkimLine, $aMatch) && !empty($aMatch[2])) + { + $sDomain = \trim($aMatch[2]); + $sDomain = \trim($sDomain, '@.'); + } + + if (!empty($sStatus) && !empty($sDomain)) + { + $aResult[] = array($sStatus, $sDomain); + } + } + } + } + + return $aResult; + } + + /** + * @return int + */ + public function PopulateEmailColectionByDkim($oEmails) + { + if ($oEmails && $oEmails instanceof \MailSo\Mime\EmailCollection) + { + $aDkimStatuses = $this->DkimStatuses(); + if (\is_array($aDkimStatuses) && 0 < \count($aDkimStatuses)) + { + $oEmails->ForeachList(function (/* @var $oItem \MailSo\Mime\Email */ $oItem) use ($aDkimStatuses) { + if ($oItem && $oItem instanceof \MailSo\Mime\Email) + { + $sEmailDomain = $oItem->GetDomain(); + foreach ($aDkimStatuses as $aDkimData) + { + if (isset($aDkimData[0], $aDkimData[1]) && $sEmailDomain === $aDkimData[1]) + { + $oItem->SetDkimStatus($aDkimData[0]); + } + } + } + }); + } + } + } + /** * @return string */ diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php index a1a6faae2..73b513a51 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -8274,7 +8274,8 @@ class Actions { $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array( 'Name' => \MailSo\Base\Utils::Utf8Clear($mResponse->GetDisplayName()), - 'Email' => \MailSo\Base\Utils::Utf8Clear($mResponse->GetEmail(true)) + 'Email' => \MailSo\Base\Utils::Utf8Clear($mResponse->GetEmail(true)), + 'DkimStatus' => $mResponse->GetDkimStatus() )); } else if ('RainLoop\Providers\AddressBook\Classes\Contact' === $sClassName) diff --git a/rainloop/v/0.0.0/app/templates/Views/User/MailMessageView.html b/rainloop/v/0.0.0/app/templates/Views/User/MailMessageView.html index 19392303e..75d5f95b3 100644 --- a/rainloop/v/0.0.0/app/templates/Views/User/MailMessageView.html +++ b/rainloop/v/0.0.0/app/templates/Views/User/MailMessageView.html @@ -217,6 +217,8 @@
+   + :