Changes for BIMI-Selector #1394

This commit is contained in:
the-djmaze 2024-01-22 00:01:46 +01:00
parent 8292c47f7c
commit 58955f792a
5 changed files with 28 additions and 10 deletions

View file

@ -39,9 +39,15 @@
avatars = new Map,
ncAvatars = new Map,
templateId = 'MailMessageView',
getBimiSelector = msg => {
// Get 's' value out of 'v=BIMI1; s=foo;'
let bimiSelector = msg.headers().valueByName('BIMI-Selector');
bimiSelector = bimiSelector ? bimiSelector.match(/;.*s=([^\s;]+)/)[1] : '';
return bimiSelector || '';
},
getAvatarUid = msg => {
let from = msg.from[0],
bimi = 'pass' == from.dkimStatus ? 1 : 0;
bimi = ('pass' == from.dkimStatus ? 1 : 0) + '-' + getBimiSelector(msg);
return `${bimi}/${from.email.toLowerCase()}`;
},
getAvatar = msg => ncAvatars.get(msg.from[0].email.toLowerCase()) || avatars.get(getAvatarUid(msg)),
@ -97,6 +103,7 @@
runQueue();
}, 'Avatar', {
bimi: 'pass' == from.dkimStatus ? 1 : 0,
bimiSelector: getBimiSelector(item[0]),
email: from.email
});
break;

View file

@ -84,8 +84,9 @@ class AvatarsPlugin extends \RainLoop\Plugins\AbstractPlugin
public function DoAvatar() : array
{
$bBimi = !empty($this->jsonParam('bimi'));
$sBimiSelector = $this->jsonParam('bimiSelector') ?: '';
$sEmail = $this->jsonParam('email');
$aResult = $this->getAvatar($sEmail, !empty($bBimi));
$aResult = $this->getAvatar($sEmail, $bBimi, $sBimiSelector);
if ($aResult) {
$aResult = [
'type' => $aResult[0],
@ -103,7 +104,9 @@ class AvatarsPlugin extends \RainLoop\Plugins\AbstractPlugin
public function ServiceAvatar(string $sServiceName, string $sBimi, string $sEmail)
{
$sEmail = \SnappyMail\Crypt::DecryptUrlSafe($sEmail);
if ($sEmail && ($aResult = $this->getAvatar($sEmail, !empty($sBimi)))) {
$aBimi = \explode('-', $sBimi, 2);
$sBimiSelector = isset($aBimi[1]) ? $aBimi[1] : 'default';
if ($sEmail && ($aResult = $this->getAvatar($sEmail, !empty($aBimi[0]), $sBimiSelector))) {
\header('Content-Type: '.$aResult[0]);
echo $aResult[1];
} else {
@ -190,7 +193,7 @@ class AvatarsPlugin extends \RainLoop\Plugins\AbstractPlugin
return null;
}
private function getAvatar(string $sEmail, bool $bBimi) : ?array
private function getAvatar(string $sEmail, bool $bBimi, string $sBimiSelector = '') : ?array
{
if (!\strpos($sEmail, '@')) {
return null;
@ -235,7 +238,7 @@ class AvatarsPlugin extends \RainLoop\Plugins\AbstractPlugin
$aUrls = [];
if ($this->Config()->Get('plugin', 'bimi', false)) {
$BIMI = $bBimi ? \SnappyMail\DNS::BIMI($sDomain) : null;
$BIMI = $bBimi ? \SnappyMail\DNS::BIMI($sDomain, $sBimiSelector) : null;
if ($BIMI) {
$aUrls[] = $BIMI;
// $aResult = ['text/uri-list', $BIMI];

View file

@ -75,6 +75,8 @@ class MailClient
MimeHeader::LIST_UNSUBSCRIBE,
// https://autocrypt.org/level1.html#the-autocrypt-header
MimeHeader::AUTOCRYPT,
// https://www.ietf.org/archive/id/draft-brand-indicators-for-message-identification-04.html#bimi-selector
MimeHeader::BIMI_SELECTOR,
// SPAM
MimeHeader::X_SPAM_STATUS,
MimeHeader::X_SPAM_FLAG,

View file

@ -93,5 +93,8 @@ abstract class Header
// https://autocrypt.org/level1.html#the-autocrypt-header
AUTOCRYPT = 'Autocrypt',
// https://www.ietf.org/archive/id/draft-brand-indicators-for-message-identification-04.html#bimi-selector
BIMI_SELECTOR = 'BIMI-Selector',
LIST_UNSUBSCRIBE = 'List-Unsubscribe';
}

View file

@ -6,12 +6,15 @@ abstract class DNS
{
/**
* $domain = 'bimigroup.org'
* $selector = 'default'
* Then a TXT lookup is done on 'default._bimi.bimigroup.org'
*/
public static function BIMI(string $domain) : string
public static function BIMI(string $domain, string $selector = 'default') : string
{
$selector = \trim($selector) ?: 'default';
$oCache = \RainLoop\Api::Actions()->Cacher();
$BIMI = $oCache->Get("dns-bimi-{$domain}") ?: null;
$sCacheKey = "dns-bimi-{$domain}-{$selector}";
$BIMI = $oCache->Get($sCacheKey) ?: null;
if ($BIMI) {
$BIMI = \json_decode($BIMI);
if ($BIMI[1] < \time()) {
@ -22,12 +25,12 @@ abstract class DNS
}
if (null === $BIMI) {
$BIMI = '';
$values = \dns_get_record("default._bimi.{$domain}", \DNS_TXT);
$values = \dns_get_record("{$selector}._bimi.{$domain}", \DNS_TXT);
if ($values) {
foreach ($values as $value) {
if (\str_starts_with($value['txt'], 'v=BIMI1')) {
$BIMI = \preg_replace('/^.+l=([^;]+)(;.*)?$/D', '$1', $value['txt']);
$oCache->Set("dns-bimi-{$domain}", \json_encode([
$oCache->Set($sCacheKey, \json_encode([
$BIMI,
time() + $value['ttl']
]));
@ -37,7 +40,7 @@ abstract class DNS
}
if (!$BIMI) {
// Don't lookup for 24 hours
$oCache->Set("dns-bimi-{$domain}", \json_encode([
$oCache->Set($sCacheKey, \json_encode([
$BIMI,
time() + 86400
]));