mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-31 04:59:21 +03:00
Return all fetched messages headers in JSON.
This is in preperation of BIMI-Selectors #1394
This commit is contained in:
parent
55a5fb491a
commit
8292c47f7c
7 changed files with 135 additions and 69 deletions
|
|
@ -14,6 +14,7 @@ import { SettingsUserStore } from 'Stores/User/Settings';
|
|||
import { FileInfo, RFC822 } from 'Common/File';
|
||||
import { AttachmentCollectionModel } from 'Model/AttachmentCollection';
|
||||
import { EmailCollectionModel } from 'Model/EmailCollection';
|
||||
import { MimeHeaderCollectionModel } from 'Model/MimeHeaderCollection';
|
||||
import { AbstractModel } from 'Knoin/AbstractModel';
|
||||
|
||||
import PreviewHTML from 'Html/PreviewMessage.html';
|
||||
|
|
@ -122,6 +123,7 @@ export class MessageModel extends AbstractModel {
|
|||
this.threadUnseen = ko.observableArray();
|
||||
this.unsubsribeLinks = ko.observableArray();
|
||||
this.flags = ko.observableArray();
|
||||
this.headers = ko.observableArray(new MimeHeaderCollectionModel);
|
||||
|
||||
addComputablesTo(this, {
|
||||
attachmentIconClass: () =>
|
||||
|
|
@ -224,8 +226,44 @@ export class MessageModel extends AbstractModel {
|
|||
if (super.revivePropertiesFromJson(json)) {
|
||||
// this.foundCIDs = isArray(json.FoundCIDs) ? json.FoundCIDs : [];
|
||||
// this.attachments(AttachmentCollectionModel.reviveFromJson(json.attachments, this.foundCIDs));
|
||||
// this.headers(MimeHeaderCollectionModel.reviveFromJson(json.headers));
|
||||
|
||||
this.computeSenderEmail();
|
||||
|
||||
let value, headers = this.headers();
|
||||
/* // These could be by Envelope or MIME
|
||||
this.messageId = headers.valueByName('Message-Id');
|
||||
this.subject(headers.valueByName('Subject'));
|
||||
this.sender = EmailCollectionModel.fromString(headers.valueByName('Sender'));
|
||||
this.from = EmailCollectionModel.fromString(headers.valueByName('From'));
|
||||
this.replyTo = EmailCollectionModel.fromString(headers.valueByName('Reply-To'));
|
||||
this.to = EmailCollectionModel.fromString(headers.valueByName('To'));
|
||||
this.cc = EmailCollectionModel.fromString(headers.valueByName('Cc'));
|
||||
this.bcc = EmailCollectionModel.fromString(headers.valueByName('Bcc'));
|
||||
this.inReplyTo = headers.valueByName('In-Reply-To');
|
||||
|
||||
this.deliveredTo = EmailCollectionModel.fromString(headers.valueByName('Delivered-To'));
|
||||
*/
|
||||
// Priority
|
||||
value = headers.valueByName('X-MSMail-Priority')
|
||||
|| headers.valueByName('Importance')
|
||||
|| headers.valueByName('X-Priority');
|
||||
if (value) {
|
||||
if (/[h12]/.test(value[0])) {
|
||||
this.priority(1);
|
||||
} else if (/[l45]/.test(value[0])) {
|
||||
this.priority(5);
|
||||
}
|
||||
}
|
||||
|
||||
// Unsubscribe links
|
||||
value = headers.valueByName('List-Unsubscribe');
|
||||
if (value) {
|
||||
this.unsubsribeLinks(value.split(',').map(
|
||||
link => link.replace(/^[ <>]+|[ <>]+$/g, '')
|
||||
));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
13
dev/Model/MimeHeader.js
Normal file
13
dev/Model/MimeHeader.js
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import ko from 'ko';
|
||||
|
||||
import { AbstractModel } from 'Knoin/AbstractModel';
|
||||
|
||||
export class MimeHeaderModel extends AbstractModel
|
||||
{
|
||||
constructor() {
|
||||
super();
|
||||
this.name = '';
|
||||
this.value = '';
|
||||
this.parameters = ko.observableArray();
|
||||
}
|
||||
}
|
||||
32
dev/Model/MimeHeaderCollection.js
Normal file
32
dev/Model/MimeHeaderCollection.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import { AbstractCollectionModel } from 'Model/AbstractCollection';
|
||||
import { MimeHeaderModel } from 'Model/MimeHeader';
|
||||
|
||||
'use strict';
|
||||
|
||||
export class MimeHeaderCollectionModel extends AbstractCollectionModel
|
||||
{
|
||||
/**
|
||||
* @param {?Array} json
|
||||
* @returns {MimeHeaderCollectionModel}
|
||||
*/
|
||||
static reviveFromJson(items) {
|
||||
return super.reviveFromJson(items, header => MimeHeaderModel.reviveFromJson(header));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @returns {?MimeHeader}
|
||||
*/
|
||||
getByName(name)
|
||||
{
|
||||
name = name.toLowerCase();
|
||||
return this.find(header => header.name.toLowerCase() === name);
|
||||
}
|
||||
|
||||
valueByName(name)
|
||||
{
|
||||
const header = this.getByName(name);
|
||||
return header ? header.value : '';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -47,9 +47,9 @@ class MailClient
|
|||
}
|
||||
|
||||
return FetchType::BuildBodyCustomHeaderRequest(array(
|
||||
MimeHeader::RETURN_PATH,
|
||||
MimeHeader::RECEIVED,
|
||||
MimeHeader::MIME_VERSION,
|
||||
// MimeHeader::RETURN_PATH,
|
||||
// MimeHeader::RECEIVED,
|
||||
// MimeHeader::MIME_VERSION,
|
||||
MimeHeader::MESSAGE_ID,
|
||||
MimeHeader::CONTENT_TYPE,
|
||||
MimeHeader::FROM_,
|
||||
|
|
@ -67,7 +67,7 @@ class MailClient
|
|||
MimeHeader::IMPORTANCE,
|
||||
MimeHeader::X_PRIORITY,
|
||||
MimeHeader::X_DRAFT_INFO,
|
||||
MimeHeader::RETURN_RECEIPT_TO,
|
||||
// MimeHeader::RETURN_RECEIPT_TO,
|
||||
MimeHeader::DISPOSITION_NOTIFICATION_TO,
|
||||
MimeHeader::X_CONFIRM_READING_TO,
|
||||
MimeHeader::AUTHENTICATION_RESULTS,
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ class Message implements \JsonSerializable
|
|||
$sPlain = '',
|
||||
$sHtml = '',
|
||||
$References = '',
|
||||
$sDeliveryReceipt = '',
|
||||
$ReadReceipt = '';
|
||||
|
||||
private ?string
|
||||
|
|
@ -53,8 +52,7 @@ class Message implements \JsonSerializable
|
|||
$iSize = 0,
|
||||
$SpamScore = 0,
|
||||
$iInternalTimeStampInUTC = 0,
|
||||
$iHeaderTimeStampInUTC = 0,
|
||||
$iPriority = \MailSo\Mime\Enumerations\MessagePriority::NORMAL;
|
||||
$iHeaderTimeStampInUTC = 0;
|
||||
|
||||
private bool
|
||||
$bIsSpam = false;
|
||||
|
|
@ -73,7 +71,6 @@ class Message implements \JsonSerializable
|
|||
$DMARC = [],
|
||||
// $aFlags = [],
|
||||
$aFlagsLowerCase = [],
|
||||
$UnsubsribeLinks = [],
|
||||
$aThreadUIDs = [],
|
||||
$aThreadUnseenUIDs = [];
|
||||
|
||||
|
|
@ -93,6 +90,9 @@ class Message implements \JsonSerializable
|
|||
private ?AttachmentCollection
|
||||
$Attachments = null;
|
||||
|
||||
private ?\MailSo\Mime\HeaderCollection
|
||||
$Headers = null;
|
||||
|
||||
function __get($k)
|
||||
{
|
||||
return \property_exists($this, $k) ? $this->$k : null;
|
||||
|
|
@ -164,6 +164,8 @@ class Message implements \JsonSerializable
|
|||
$sHeaders = $oFetchResponse->GetHeaderFieldsValue();
|
||||
$oHeaders = \strlen($sHeaders) ? new \MailSo\Mime\HeaderCollection($sHeaders, false, $sCharset) : null;
|
||||
if ($oHeaders) {
|
||||
$oMessage->Headers = $oHeaders;
|
||||
|
||||
$sContentTypeCharset = $oHeaders->ParameterValue(
|
||||
MimeHeader::CONTENT_TYPE,
|
||||
\MailSo\Mime\Enumerations\Parameter::CHARSET
|
||||
|
|
@ -200,29 +202,8 @@ class Message implements \JsonSerializable
|
|||
$oHeaders->ValueByName(MimeHeader::DATE)
|
||||
);
|
||||
|
||||
// Priority
|
||||
$sPriority = $oHeaders->ValueByName(MimeHeader::X_MSMAIL_PRIORITY)
|
||||
?: $oHeaders->ValueByName(MimeHeader::IMPORTANCE)
|
||||
?: $oHeaders->ValueByName(MimeHeader::X_PRIORITY);
|
||||
if (\strlen($sPriority)) {
|
||||
switch (\substr(\trim($sPriority), 0, 1))
|
||||
{
|
||||
case 'h':
|
||||
case '1':
|
||||
case '2':
|
||||
$oMessage->iPriority = \MailSo\Mime\Enumerations\MessagePriority::HIGH;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
case '4':
|
||||
case '5':
|
||||
$oMessage->iPriority = \MailSo\Mime\Enumerations\MessagePriority::LOW;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Delivery Receipt
|
||||
$oMessage->sDeliveryReceipt = \trim($oHeaders->ValueByName(MimeHeader::RETURN_RECEIPT_TO));
|
||||
// $oMessage->sDeliveryReceipt = \trim($oHeaders->ValueByName(MimeHeader::RETURN_RECEIPT_TO));
|
||||
|
||||
// Read Receipt
|
||||
$oMessage->ReadReceipt = \trim($oHeaders->ValueByName(MimeHeader::DISPOSITION_NOTIFICATION_TO));
|
||||
|
|
@ -230,17 +211,6 @@ class Message implements \JsonSerializable
|
|||
$oMessage->ReadReceipt = \trim($oHeaders->ValueByName(MimeHeader::X_CONFIRM_READING_TO));
|
||||
}
|
||||
|
||||
// Unsubscribe links
|
||||
$UnsubsribeLinks = $oHeaders->ValueByName(MimeHeader::LIST_UNSUBSCRIBE);
|
||||
if ($UnsubsribeLinks) {
|
||||
$oMessage->UnsubsribeLinks = \array_map(
|
||||
function ($link) {
|
||||
return trim($link, ' <>');
|
||||
},
|
||||
\explode(',', $UnsubsribeLinks)
|
||||
);
|
||||
}
|
||||
|
||||
if ($spam = $oHeaders->ValueByName(MimeHeader::X_SPAMD_RESULT)) {
|
||||
if (\preg_match('/\\[([\\d\\.-]+)\\s*\\/\\s*([\\d\\.]+)\\];/', $spam, $match)) {
|
||||
if ($threshold = \floatval($match[2])) {
|
||||
|
|
@ -554,7 +524,6 @@ class Message implements \JsonSerializable
|
|||
'sender' => $this->oSender,
|
||||
'deliveredTo' => $this->oDeliveredTo,
|
||||
|
||||
'priority' => $this->iPriority,
|
||||
'readReceipt' => $sReadReceipt,
|
||||
'autocrypt' => $aAutocrypt ?: null,
|
||||
|
||||
|
|
@ -576,15 +545,14 @@ class Message implements \JsonSerializable
|
|||
// 'keywords' => $keywords,
|
||||
'size' => $this->iSize,
|
||||
|
||||
'preview' => $this->sPreview
|
||||
'preview' => $this->sPreview,
|
||||
|
||||
'headers' => $this->Headers
|
||||
);
|
||||
|
||||
if ($this->DraftInfo) {
|
||||
$result['draftInfo'] = $this->DraftInfo;
|
||||
}
|
||||
if ($this->UnsubsribeLinks) {
|
||||
$result['unsubsribeLinks'] = $this->UnsubsribeLinks;
|
||||
}
|
||||
if ($this->References) {
|
||||
$result['references'] = $this->References;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace MailSo\Mime;
|
|||
* @category MailSo
|
||||
* @package Mime
|
||||
*/
|
||||
class Header
|
||||
class Header implements \JsonSerializable
|
||||
{
|
||||
private string $sName;
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ class Header
|
|||
$this->sFullValue = \trim($sValue);
|
||||
$this->sEncodedValueForReparse = '';
|
||||
|
||||
if (\strlen($sEncodedValueForReparse) && $this->IsReparsed()) {
|
||||
if (\strlen($sEncodedValueForReparse) && ($this->IsEmail() || $this->IsSubject() || $this->IsParameterized())) {
|
||||
$this->sEncodedValueForReparse = \trim($sEncodedValueForReparse);
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ class Header
|
|||
|
||||
public function NameWithDelimitrom() : string
|
||||
{
|
||||
return $this->Name().': ';
|
||||
return $this->sName . ': ';
|
||||
}
|
||||
|
||||
public function Value() : string
|
||||
|
|
@ -103,7 +103,7 @@ class Header
|
|||
|
||||
public function SetParentCharset(string $sParentCharset) : Header
|
||||
{
|
||||
if ($this->sParentCharset !== $sParentCharset && $this->IsReparsed() && \strlen($this->sEncodedValueForReparse)) {
|
||||
if ($this->sParentCharset !== $sParentCharset && \strlen($this->sEncodedValueForReparse)) {
|
||||
$this->initInputData(
|
||||
$this->sName,
|
||||
\trim(\MailSo\Base\Utils::DecodeHeaderValue($this->sEncodedValueForReparse, $sParentCharset)),
|
||||
|
|
@ -132,19 +132,17 @@ class Header
|
|||
|
||||
if ($this->IsSubject()) {
|
||||
if (!\MailSo\Base\Utils::IsAscii($sResult) && \function_exists('iconv_mime_encode')) {
|
||||
$aPreferences = array(
|
||||
return \iconv_mime_encode($this->Name(), $sResult, array(
|
||||
// 'scheme' => \MailSo\Base\Enumerations\Encoding::QUOTED_PRINTABLE_SHORT,
|
||||
'scheme' => \MailSo\Base\Enumerations\Encoding::BASE64_SHORT,
|
||||
'input-charset' => \MailSo\Base\Enumerations\Charset::UTF_8,
|
||||
'output-charset' => \MailSo\Base\Enumerations\Charset::UTF_8,
|
||||
'line-length' => 74,
|
||||
'line-break-chars' => "\r\n"
|
||||
);
|
||||
|
||||
return \iconv_mime_encode($this->Name(), $sResult, $aPreferences);
|
||||
));
|
||||
}
|
||||
}
|
||||
else if ($this->IsParameterized() && 0 < $this->oParameters->count())
|
||||
else if ($this->IsParameterized() && $this->oParameters->count())
|
||||
{
|
||||
$sResult = $this->sValue.'; '.$this->oParameters->ToString(true);
|
||||
}
|
||||
|
|
@ -157,16 +155,15 @@ class Header
|
|||
}
|
||||
|
||||
// https://www.rfc-editor.org/rfc/rfc2822#section-2.1.1, avoid folding immediately after the header name
|
||||
return $this->NameWithDelimitrom() . \wordwrap($sResult, 78 - \strlen($this->NameWithDelimitrom()) - 1, "\r\n ");
|
||||
|
||||
return $this->NameWithDelimitrom() . \wordwrap($sResult, 78 - \strlen($this->NameWithDelimitrom()) - 1, "\r\n ");
|
||||
}
|
||||
|
||||
public function IsSubject() : bool
|
||||
private function IsSubject() : bool
|
||||
{
|
||||
return \strtolower(Enumerations\Header::SUBJECT) === \strtolower($this->Name());
|
||||
}
|
||||
|
||||
public function IsParameterized() : bool
|
||||
private function IsParameterized() : bool
|
||||
{
|
||||
return \in_array(\strtolower($this->sName), array(
|
||||
\strtolower(Enumerations\Header::CONTENT_TYPE),
|
||||
|
|
@ -174,7 +171,7 @@ class Header
|
|||
));
|
||||
}
|
||||
|
||||
public function IsEmail() : bool
|
||||
private function IsEmail() : bool
|
||||
{
|
||||
return \in_array(\strtolower($this->sName), array(
|
||||
\strtolower(Enumerations\Header::FROM_),
|
||||
|
|
@ -182,7 +179,7 @@ class Header
|
|||
\strtolower(Enumerations\Header::CC),
|
||||
\strtolower(Enumerations\Header::BCC),
|
||||
\strtolower(Enumerations\Header::REPLY_TO),
|
||||
\strtolower(Enumerations\Header::RETURN_PATH),
|
||||
// \strtolower(Enumerations\Header::RETURN_PATH),
|
||||
\strtolower(Enumerations\Header::SENDER)
|
||||
));
|
||||
}
|
||||
|
|
@ -199,8 +196,22 @@ class Header
|
|||
return $this->Value();
|
||||
}
|
||||
|
||||
public function IsReparsed() : bool
|
||||
private function IsReparsed() : bool
|
||||
{
|
||||
return $this->IsEmail() || $this->IsSubject() || $this->IsParameterized();
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
$aResult = array(
|
||||
'@Object' => 'Object/MimeHeader',
|
||||
'name' => $this->sName,
|
||||
'value' => $this->sValue
|
||||
);
|
||||
if ($this->oParameters->count()) {
|
||||
$aResult['parameters'] = $this->oParameters;
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,15 +81,10 @@ class HeaderCollection extends \MailSo\Base\Collection
|
|||
);
|
||||
}
|
||||
|
||||
public function ParametersByName(string $sHeaderName) : ?ParameterCollection
|
||||
{
|
||||
$oHeader = $this->GetByName($sHeaderName);
|
||||
return $oHeader ? $oHeader->Parameters() : null;
|
||||
}
|
||||
|
||||
public function ParameterValue(string $sHeaderName, string $sParamName) : string
|
||||
{
|
||||
$oParameters = $this->ParametersByName($sHeaderName);
|
||||
$oHeader = $this->GetByName($sHeaderName);
|
||||
$oParameters = $oHeader ? $oHeader->Parameters() : null;
|
||||
return (null !== $oParameters) ? $oParameters->ParameterValueByName($sParamName) : '';
|
||||
}
|
||||
|
||||
|
|
@ -244,4 +239,13 @@ class HeaderCollection extends \MailSo\Base\Collection
|
|||
{
|
||||
return \implode("\r\n", $this->getArrayCopy());
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return array(
|
||||
'@Object' => 'Collection/MimeHeaderCollection',
|
||||
'@Collection' => $this->getArrayCopy()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue