20
plugins/avatars/LICENSE
Normal file
|
@ -0,0 +1,20 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 RainLoop Team
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
43
plugins/avatars/avatars.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
(rl => {
|
||||
// if (rl.settings.get('Nextcloud'))
|
||||
const
|
||||
templateId = 'MailMessageView';
|
||||
// DATA_IMAGE_USER_DOT_PIC = 'data:image/svg+xml;utf8,<svg version="1.1" xml:space="preserve" width="74.279999" height="86.666664" viewBox="0 0 74.279999 86.666664" xmlns="http://www.w3.org/2000/svg"><path d="M 557.17264,0 25.567509,-0.90909091 C 3.878663,-1.0561896 0.22727273,-0.69278176 0,92.8594 0,215.105 185.715,278.574 185.715,278.574 c 0,0 10.629,18.985 0,46.426 -39.047,28.785 -43.828,73.824 -46.43,185.715 C 147.316,622.742 225.969,650 278.57,650 331.18,650 409.82,622.793 417.859,510.715 415.262,398.824 410.477,353.785 371.434,325 c -10.637,-27.395 0,-46.426 0,-46.426 0,0 185.711,-63.469 185.711,-185.7146" style="fill:#AAAAAA;fill-opacity:1;fill-rule:nonzero;stroke:none" transform="matrix(0.13333333,0,0,-0.13333333,0,86.666667)"/></svg>';
|
||||
|
||||
addEventListener('rl-view-model.create', e => {
|
||||
if (templateId === e.detail.viewModelTemplateID) {
|
||||
|
||||
const
|
||||
template = document.getElementById(templateId),
|
||||
messageItemHeader = template.content.querySelector('.messageItemHeader');
|
||||
|
||||
if (messageItemHeader) {
|
||||
messageItemHeader.prepend(Element.fromHTML(
|
||||
`<img class="fromPic" data-bind="visible: viewUserPicVisible, attr: {'src': viewUserPic() }">`
|
||||
));
|
||||
}
|
||||
|
||||
let view = e.detail;
|
||||
view.viewUserPic = ko.observable('');
|
||||
view.viewUserPicVisible = ko.observable(false);
|
||||
|
||||
view.message.subscribe(msg => {
|
||||
if (msg) {
|
||||
let from = msg.from[0],
|
||||
bimi = 'pass' == from.dkimStatus ? 1 : 0;
|
||||
// view.viewUserPic(`?Avatar/${bimi}/${encodeURIComponent(from.email)}`);
|
||||
rl.pluginRemoteRequest((iError, data) => {
|
||||
if (!iError && data?.Result.type) {
|
||||
view.viewUserPic(`data:${data.Result.type};base64,${data.Result.data}`);
|
||||
view.viewUserPicVisible(true);
|
||||
}
|
||||
}, 'Avatar', {
|
||||
bimi: bimi,
|
||||
email: from.email
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
})(window.rl);
|
BIN
plugins/avatars/images/empty-contact.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
plugins/avatars/images/services/amazon.com.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
plugins/avatars/images/services/apple.com.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
plugins/avatars/images/services/asana.com.png
Normal file
After Width: | Height: | Size: 995 B |
BIN
plugins/avatars/images/services/battle.net.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
plugins/avatars/images/services/blizzard.com.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
plugins/avatars/images/services/cnet.online.com.png
Normal file
After Width: | Height: | Size: 6.5 KiB |
BIN
plugins/avatars/images/services/connect.asana.com.png
Normal file
After Width: | Height: | Size: 995 B |
BIN
plugins/avatars/images/services/e.paypal.com.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
plugins/avatars/images/services/ea.com.png
Normal file
After Width: | Height: | Size: 6 KiB |
BIN
plugins/avatars/images/services/ebay.com.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
plugins/avatars/images/services/em.ea.com.png
Normal file
After Width: | Height: | Size: 6 KiB |
BIN
plugins/avatars/images/services/email.blizzard.com.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
plugins/avatars/images/services/email.microsoft.com.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
plugins/avatars/images/services/email.skype.com.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
plugins/avatars/images/services/facebook.com.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
plugins/avatars/images/services/facebookmail.com.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
plugins/avatars/images/services/github.com.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
plugins/avatars/images/services/google.com.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
plugins/avatars/images/services/id.apple.com.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
plugins/avatars/images/services/intl.paypal.com.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
plugins/avatars/images/services/microsoft.com.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
plugins/avatars/images/services/microsoftonline.com.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
plugins/avatars/images/services/myspace.com.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
plugins/avatars/images/services/news.myspace.com.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
plugins/avatars/images/services/news.onlive.com.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
plugins/avatars/images/services/onlive.com.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
plugins/avatars/images/services/paypal.com.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
plugins/avatars/images/services/plus.google.com.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
plugins/avatars/images/services/postmaster.twitter.com.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
plugins/avatars/images/services/reply.ebay.com.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
plugins/avatars/images/services/reply1.ebay.com.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
plugins/avatars/images/services/reply2.ebay.com.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
plugins/avatars/images/services/reply3.ebay.com.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
plugins/avatars/images/services/skype.com.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
plugins/avatars/images/services/steampowered.com.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
plugins/avatars/images/services/ted.com.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
plugins/avatars/images/services/twitter.com.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
plugins/avatars/images/services/youtube.com.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
112
plugins/avatars/index.php
Normal file
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
|
||||
class AvatarsPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||
{
|
||||
const
|
||||
NAME = 'Avatar',
|
||||
AUTHOR = 'SnappyMail',
|
||||
URL = 'https://snappymail.eu/',
|
||||
VERSION = '1.0',
|
||||
RELEASE = '2022-11-11',
|
||||
REQUIRED = '2.21.0',
|
||||
CATEGORY = 'Contacts',
|
||||
LICENSE = 'MIT',
|
||||
DESCRIPTION = '';
|
||||
|
||||
public function Init() : void
|
||||
{
|
||||
$this->addCss('style.css');
|
||||
$this->addJs('avatars.js');
|
||||
$this->addJsonHook('Avatar', 'DoAvatar');
|
||||
$this->addPartHook('Avatar', 'ServiceAvatar');
|
||||
}
|
||||
|
||||
public function DoAvatar() : array
|
||||
{
|
||||
$bBimi = !empty($this->jsonParam('bimi'));
|
||||
$sEmail = $this->jsonParam('email');
|
||||
$aResult = static::getAvatar(\urldecode($sEmail), !empty($sEmail));
|
||||
if ($aResult) {
|
||||
$aResult = [
|
||||
'type' => $aResult[0],
|
||||
'data' => \base64_encode($aResult[1])
|
||||
];
|
||||
}
|
||||
return $this->jsonResponse(__FUNCTION__, $aResult);
|
||||
}
|
||||
|
||||
// public function ServiceAvatar(...$aParts)
|
||||
public function ServiceAvatar(string $sServiceName, string $sBimi, string $sEmail)
|
||||
{
|
||||
$aResult = static::getAvatar(\urldecode($sEmail), !empty($sEmail));
|
||||
if ($aResult) {
|
||||
\header('Content-Type: '.$aResult[0]);
|
||||
echo $aResult[1];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static function getAvatar(string $sEmail, bool $bBimi) : ?array
|
||||
{
|
||||
if (!\strpos($sEmail, '@')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// $this->verifyCacheByKey($sEmail);
|
||||
|
||||
// DATA_IMAGE_USER_DOT_PIC
|
||||
$sDomain = \explode('@', $sEmail);
|
||||
$sDomain = \array_pop($sDomain);
|
||||
|
||||
$BIMI = $bBimi ? \SnappyMail\DNS::BIMI($sDomain) : null;
|
||||
// TODO: process $BIMI value
|
||||
|
||||
// TODO: lookup contacts vCard
|
||||
|
||||
// TODO: make this optional
|
||||
$aResult = static::Gravatar($sEmail);
|
||||
|
||||
if (!$aResult && \file_exists(__DIR__ . '/images/services/'.$sDomain.'.png')) {
|
||||
$aResult = [
|
||||
'image/png',
|
||||
\file_get_contents(__DIR__ . '/images/services/'.$sDomain.'.png')
|
||||
];
|
||||
}
|
||||
if (!$aResult) {
|
||||
$aResult = [
|
||||
'image/png',
|
||||
\file_get_contents(__DIR__.'/images/empty-contact.png')
|
||||
];
|
||||
}
|
||||
|
||||
// $this->cacheByKey($sEmail);
|
||||
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
private static function Gravatar(string $sEmail) : ?array
|
||||
{
|
||||
$sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail, true);
|
||||
$sGravatarUrl = 'http://gravatar.com/avatar/'.\md5(\strtolower($sEmail)).'?s=80&d=404';
|
||||
$oHTTP = \SnappyMail\HTTP\Request::factory(/*'socket' or 'curl'*/);
|
||||
$oHTTP->proxy = \RainLoop\Api::Config()->Get('labs', 'curl_proxy', '');
|
||||
$oHTTP->proxy_auth = \RainLoop\Api::Config()->Get('labs', 'curl_proxy_auth', '');
|
||||
$oHTTP->max_response_kb = 0;
|
||||
$oHTTP->timeout = 15; // timeout in seconds.
|
||||
$oResponse = $oHTTP->doRequest('GET', $sGravatarUrl);
|
||||
if ($oResponse) {
|
||||
if (200 === $oResponse->status && \str_starts_with($oResponse->getHeader('content-type'), 'image/')) {
|
||||
return [
|
||||
$oResponse->getHeader('content-type'),
|
||||
$oResponse->body
|
||||
];
|
||||
}
|
||||
\SnappyMail\Log::notice('Gravatar', "error {$oResponse->status} for {$sGravatarUrl}");
|
||||
} else {
|
||||
\SnappyMail\Log::warning('Gravatar', "failed for {$sGravatarUrl}");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
11
plugins/avatars/style.css
Normal file
|
@ -0,0 +1,11 @@
|
|||
.messageView .b-content .messageItemHeader .fromPic {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
padding: 2px;
|
||||
margin: 0 5px 0 0;
|
||||
background: #fff;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 6px;
|
||||
}
|
|
@ -257,19 +257,12 @@ class Email implements \JsonSerializable
|
|||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
/*
|
||||
$BIMI = '';
|
||||
if (Enumerations\DkimStatus::PASS == $this->GetDkimStatus()) {
|
||||
$BIMI = \SnappyMail\DNS\BIMI($this->GetDomain());
|
||||
}
|
||||
*/
|
||||
return array(
|
||||
'@Object' => 'Object/Email',
|
||||
'Name' => \MailSo\Base\Utils::Utf8Clear($this->GetDisplayName()),
|
||||
'Email' => \MailSo\Base\Utils::Utf8Clear($this->GetEmail(true)),
|
||||
'DkimStatus' => $this->GetDkimStatus(),
|
||||
'DkimValue' => $this->GetDkimValue()
|
||||
// 'BIMI' => $BIMI
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|