Skip to content
Closed
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
8 changes: 8 additions & 0 deletions lib/Db/LocalMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
* @method setRaw(string|null $raw)
* @method bool getRequestMdn()
* @method setRequestMdn(bool $mdn)
* @method void setAiGenerated(bool $aiGenerated)
* @method bool|null getAiGenerated()
*/
class LocalMessage extends Entity implements JsonSerializable {
public const TYPE_OUTGOING = 0;
Expand Down Expand Up @@ -141,6 +143,8 @@ class LocalMessage extends Entity implements JsonSerializable {
/** @var bool */
protected $requestMdn;

protected $aiGenerated = false;

public function __construct() {
$this->addType('type', 'integer');
$this->addType('accountId', 'integer');
Expand All @@ -155,6 +159,7 @@ public function __construct() {
$this->addType('smimeEncrypt', 'boolean');
$this->addType('status', 'integer');
$this->addType('requestMdn', 'boolean');
$this->addType('aiGenerated', 'boolean');

}

Expand Down Expand Up @@ -227,4 +232,7 @@ public function setRecipients(array $recipients): void {
public function getRecipients(): ?array {
return $this->recipients;
}
public function isAiGenerated(): bool {
return $this->getAiGenerated() === true;
}
}
6 changes: 6 additions & 0 deletions lib/Db/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
* @method string|null getInReplyTo()
* @method string|null getThreadRootId()
* @method void setMailboxId(int $mailbox)
* @method void setFlagAiGenerated(bool $aiGenerated)
* @method bool|null getFlagAiGenerated()
* @method int getMailboxId()
* @method void setSubject(string $subject)
* @method string getSubject()
Expand Down Expand Up @@ -91,6 +93,7 @@
];

protected $uid;
protected $flagAiGenerated;
protected $messageId;
protected $references;
protected $inReplyTo;
Expand Down Expand Up @@ -167,6 +170,7 @@
$this->addType('flagAttachments', 'boolean');
$this->addType('flagImportant', 'boolean');
$this->addType('flagMdnsent', 'boolean');
$this->addType('flagAiGenerated', 'boolean');
$this->addType('updatedAt', 'integer');
$this->addType('imipMessage', 'boolean');
$this->addType('imipProcessed', 'boolean');
Expand Down Expand Up @@ -345,6 +349,7 @@
'subject' => $this->getSubject(),
'dateInt' => $this->getSentAt(),
'flags' => [
'aiGenerated' => ($this->getFlagAiGenerated() === true),
'seen' => ($this->getFlagSeen() === true),
'flagged' => ($this->getFlagFlagged() === true),
'answered' => ($this->getFlagAnswered() === true),
Expand All @@ -356,6 +361,7 @@
'$junk' => ($this->getFlagJunk() === true),
'$notjunk' => ($this->getFlagNotjunk() === true),
'$mdnsent' => ($this->getFlagMdnsent() === true),
'aiGenerated' => ($this->getFlagAiGenerated() === true),

Check failure on line 364 in lib/Db/Message.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis dev-master

DuplicateArrayKey

lib/Db/Message.php:364:5: DuplicateArrayKey: Key 'aiGenerated' already exists on array (see https://psalm.dev/151)

Check failure on line 364 in lib/Db/Message.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis dev-stable34

DuplicateArrayKey

lib/Db/Message.php:364:5: DuplicateArrayKey: Key 'aiGenerated' already exists on array (see https://psalm.dev/151)

Check failure on line 364 in lib/Db/Message.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis dev-stable32

DuplicateArrayKey

lib/Db/Message.php:364:5: DuplicateArrayKey: Key 'aiGenerated' already exists on array (see https://psalm.dev/151)

Check failure on line 364 in lib/Db/Message.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis dev-stable33

DuplicateArrayKey

lib/Db/Message.php:364:5: DuplicateArrayKey: Key 'aiGenerated' already exists on array (see https://psalm.dev/151)
],
'tags' => $indexed,
'from' => $this->getFrom()->jsonSerialize(),
Expand Down
7 changes: 7 additions & 0 deletions lib/IMAP/ImapMessageFetcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
private string $rawReferences = '';
private string $dispositionNotificationTo = '';
private bool $hasDkimSignature = false;

private bool $isAiGenerated = false;
private array $phishingDetails = [];
private ?string $unsubscribeUrl = null;
private bool $isOneClickUnsubscribe = false;
Expand Down Expand Up @@ -259,7 +261,7 @@
$messageId = new Horde_Mail_Rfc822_Identification($envelope->message_id);
$inReplyTo = new Horde_Mail_Rfc822_Identification($envelope->in_reply_to);

return new IMAPMessage(

Check failure on line 264 in lib/IMAP/ImapMessageFetcher.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis dev-master

TooManyArguments

lib/IMAP/ImapMessageFetcher.php:264:10: TooManyArguments: Too many arguments for OCA\Mail\Model\IMAPMessage::__construct - expecting 30 but saw 31 (see https://psalm.dev/026)

Check failure on line 264 in lib/IMAP/ImapMessageFetcher.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis dev-stable34

TooManyArguments

lib/IMAP/ImapMessageFetcher.php:264:10: TooManyArguments: Too many arguments for OCA\Mail\Model\IMAPMessage::__construct - expecting 30 but saw 31 (see https://psalm.dev/026)

Check failure on line 264 in lib/IMAP/ImapMessageFetcher.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis dev-stable32

TooManyArguments

lib/IMAP/ImapMessageFetcher.php:264:10: TooManyArguments: Too many arguments for OCA\Mail\Model\IMAPMessage::__construct - expecting 30 but saw 31 (see https://psalm.dev/026)

Check failure on line 264 in lib/IMAP/ImapMessageFetcher.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis dev-stable33

TooManyArguments

lib/IMAP/ImapMessageFetcher.php:264:10: TooManyArguments: Too many arguments for OCA\Mail\Model\IMAPMessage::__construct - expecting 30 but saw 31 (see https://psalm.dev/026)
$this->uid,
$messageId->ids[0] ?? '',
$fetch->getFlags(),
Expand Down Expand Up @@ -290,6 +292,7 @@
$signatureIsValid,
$this->htmlService, // TODO: drop the html service dependency
$this->isPgpMimeEncrypted,
$this->isAiGenerated,
);
}

Expand Down Expand Up @@ -554,6 +557,10 @@
$dkimSignatureHeader = $parsedHeaders->getHeader('dkim-signature');
$this->hasDkimSignature = $dkimSignatureHeader !== null;

$aiGeneratedHeader = $parsedHeaders->getHeader('x-ai-generated');
$this->isAiGenerated = $aiGeneratedHeader !== null
&& strtolower($aiGeneratedHeader->value_single) === 'true';

if ($this->runPhishingCheck) {
$this->phishingDetails = $this->phishingDetectionService->checkHeadersForPhishing($this->userId, $parsedHeaders, $fetch->getFlags(), $this->hasHtmlMessage, $this->htmlMessage);
}
Expand Down
30 changes: 30 additions & 0 deletions lib/Migration/Version5090Date20260528000000.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace OCA\Mail\Migration;

use Closure;
use OCP\DB\ISchemaWrapper;
use OCP\DB\Types;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;

class Version5090Date20260528000000 extends SimpleMigrationStep {

public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
$table = $schema->getTable('mail_messages');

if (!$table->hasColumn('flag_ai_generated')) {
$table->addColumn('flag_ai_generated', Types::BOOLEAN, [
'notnull' => false,
'default' => false,
]);
}

return $schema;
}
}

5 changes: 5 additions & 0 deletions lib/Model/IMAPMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class IMAPMessage implements IMessage, JsonSerializable {
private bool $isSigned;
private bool $signatureIsValid;
private bool $isPgpMimeEncrypted;
private bool $isAiGenerated = false;

/**
* @param list<IMAPAttachment> $inlineAttachments
Expand Down Expand Up @@ -151,6 +152,10 @@ public static function generateMessageId(): string {
return Horde_Mime_Headers_MessageId::create('nextcloud-mail-generated')->value;
}

public function isAiGenerated(): bool {
return $this->isAiGenerated;
}

public function hasHtmlMessage(): bool {
return $this->hasHtmlMessage;
}
Expand Down
4 changes: 4 additions & 0 deletions lib/Service/MailTransmission.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ public function sendMessage(Account $account, LocalMessage $localMessage): void
$headers['In-Reply-To'] = $inReplyTo;
}

if ($localMessage->isAiGenerated()) {
$headers['X-AI-Generated'] = 'true';
}

if ($localMessage->getRequestMdn()) {
$headers[Horde_Mime_Mdn::MDN_HEADER] = $from->toHorde();
}
Expand Down
12 changes: 12 additions & 0 deletions src/components/ThreadEnvelope.vue
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@
<div v-if="hasChangedSubject" class="subline">
{{ cleanSubject }}
</div>
<div v-if="envelope.flags.aiGenerated" class="subline subline--ai-generated">
<AiIcon :size="14" />
<span>{{ t('mail', 'Contains AI generated content') }}</span>
</div>
<div v-if="showSubline" class="subline">
<span class="preview">
{{ isEncrypted ? t('mail', 'Encrypted message') : envelope.previewText }}
Expand Down Expand Up @@ -373,6 +377,7 @@ import { NcActionButton, NcButton } from '@nextcloud/vue'
import { mapStores } from 'pinia'
import NcActions from '@nextcloud/vue/components/NcActions'
import NcActionText from '@nextcloud/vue/components/NcActionText'
import AiIcon from '@nextcloud/vue/components/NcAssistantIcon'
import ArchiveIcon from 'vue-material-design-icons/ArchiveArrowDownOutline.vue'
import ChevronDownIcon from 'vue-material-design-icons/ChevronDown.vue'
import ChevronUpIcon from 'vue-material-design-icons/ChevronUp.vue'
Expand Down Expand Up @@ -442,6 +447,7 @@ export default {
Error,
IconFavorite,
JunkIcon,
AiIcon,
MessageLoadingSkeleton,
MenuEnvelope,
Moment,
Expand Down Expand Up @@ -1477,4 +1483,10 @@ export default {
display: inline;
align-items: center;
}
.subline--ai-generated {
display: flex;
align-items: center;
gap: 4px;
opacity: 0.8;
}
</style>
Loading