Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions apps/theming/lib/ThemingDefaults.php
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,16 @@ public function getLogo($useSvg = true): string {
return $this->urlGenerator->linkToRoute('theming.Theming.getImage', [ 'key' => 'logo', 'useSvg' => $useSvg, 'v' => $cacheBusterCounter ]);
}

#[\Override]
public function getLogoImage(): ?array {
try {
$file = $this->imageManager->getImage('logo', false);
return ['content' => $file->getContent(), 'mimeType' => $file->getMimeType()];
} catch (\Exception $e) {
return parent::getLogoImage();
}
}

/**
* Themed background image url
*
Expand Down
23 changes: 21 additions & 2 deletions lib/private/Mail/EMailTemplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class EMailTemplate implements IEMailTemplate {
protected bool $bodyListOpened = false;
/** indicated if the footer is added */
protected bool $footerAdded = false;
/** @var array<array{name: string, content: string, mimeType: string}> images to embed inline, referenced via cid: */
protected array $inlineImages = [];

protected string $head = <<<EOF
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Expand Down Expand Up @@ -355,8 +357,25 @@ public function addHeader(): void {
$logoSizeDimensions = ' width="' . $this->logoWidth . '" height="' . $this->logoHeight . '"';
}

$logoUrl = $this->urlGenerator->getAbsoluteURL($this->themingDefaults->getLogo(false));
$this->htmlBody .= vsprintf($this->header, [$this->themingDefaults->getDefaultColorPrimary(), $logoUrl, $this->themingDefaults->getName(), $logoSizeDimensions]);
$logoImage = $this->themingDefaults->getLogoImage();
if ($logoImage !== null) {
// Embed the logo directly in the message instead of linking to it, so mail
// clients don't have to fetch it from the internet (some (e.g. gmail) block that).
$logoSrc = 'cid:logo';
$this->inlineImages[] = ['name' => 'logo'] + $logoImage;
} else {
$logoSrc = $this->urlGenerator->getAbsoluteURL($this->themingDefaults->getLogo(false));
}
$this->htmlBody .= vsprintf($this->header, [$this->themingDefaults->getDefaultColorPrimary(), $logoSrc, $this->themingDefaults->getName(), $logoSizeDimensions]);
}

/**
* Images that must be embedded inline in the message, referenced via `cid:<name>` in the HTML body
*
* @return array<array{name: string, content: string, mimeType: string}>
*/
public function getInlineImages(): array {
return $this->inlineImages;
}

/**
Expand Down
5 changes: 5 additions & 0 deletions lib/private/Mail/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,11 @@ public function useTemplate(IEMailTemplate $emailTemplate): IMessage {
$this->setPlainBody($emailTemplate->renderText());
if (!$this->plainTextOnly) {
$this->setHtmlBody($emailTemplate->renderHtml());
if ($emailTemplate instanceof EMailTemplate) {
foreach ($emailTemplate->getInlineImages() as $image) {
$this->attachInline($image['content'], $image['name'], $image['mimeType']);
}
}
}
return $this;
}
Expand Down
18 changes: 18 additions & 0 deletions lib/private/legacy/OC_Defaults.php
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,24 @@ public function getLogo($useSvg = true) {
return $logo . '?v=' . hash('sha1', implode('.', Util::getVersion()));
}

/**
* Raw logo image data (raster, not SVG) for embedding directly into emails,
* so mail clients don't have to fetch it from the internet.
*
* @return array{content: string, mimeType: string}|null null when unavailable
*/
public function getLogoImage(): ?array {
if ($this->themeExist('getLogoImage')) {
return $this->theme->getLogoImage();
}

$content = @file_get_contents(\OC::$SERVERROOT . '/core/img/logo/logo.png');
if ($content === false) {
return null;
}
return ['content' => $content, 'mimeType' => 'image/png'];
}

public function getTextColorPrimary() {
if ($this->themeExist('getTextColorPrimary')) {
return $this->theme->getTextColorPrimary();
Expand Down
10 changes: 10 additions & 0 deletions lib/public/Defaults.php
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,16 @@ public function getLogo(bool $useSvg = true): string {
return $this->defaults->getLogo($useSvg);
}

/**
* Raw logo image data (raster) for embedding directly into emails
*
* @return array{content: string, mimeType: string}|null null when unavailable
* @since 35.0.0
*/
public function getLogoImage(): ?array {
return $this->defaults->getLogoImage();
}

/**
* Returns primary color
* @return string
Expand Down
16 changes: 16 additions & 0 deletions tests/lib/Mail/EMailTemplateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -217,4 +217,20 @@ public function testEMailTemplateAlternativePlainTexts(): void {
$expectedTXT = file_get_contents(\OC::$SERVERROOT . '/tests/data/emails/new-account-email-custom-text-alternative.txt');
$this->assertSame($expectedTXT, $this->emailTemplate->renderText());
}

public function testEMailTemplateEmbedsLogo(): void {
$this->defaults->method('getDefaultColorPrimary')->willReturn('#0082c9');
$this->defaults->method('getName')->willReturn('TestCloud');
$this->defaults->method('getLogoImage')
->willReturn(['content' => 'PNGDATA', 'mimeType' => 'image/png']);
$this->urlGenerator->expects($this->never())->method('getAbsoluteURL');

$this->emailTemplate->addHeader();

$this->assertStringContainsString('src="cid:logo"', $this->emailTemplate->renderHtml());
$this->assertSame(
[['name' => 'logo', 'content' => 'PNGDATA', 'mimeType' => 'image/png']],
$this->emailTemplate->getInlineImages()
);
}
}