Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to resend e-mails when transport fails #54

Merged
merged 34 commits into from Oct 14, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
4a89f80
Allow to resend e-mails when transport fails
wirduzen-felix Sep 12, 2023
2e77ce7
Remove `AFTER` from Migration query
wirduzen-felix Sep 12, 2023
40c7975
Fix german translation for transportFailed alert
schneider-felix Sep 12, 2023
250cf35
Fix english translation for mail delivery failed alert
schneider-felix Sep 12, 2023
257ddaa
Improve readability of SaveMail in MailSender
schneider-felix Sep 12, 2023
b337ba6
Add resend history
wirduzen-felix Sep 14, 2023
8435f6e
Merge branch 'failed-mails-storage' of github-private:schneider-felix…
wirduzen-felix Sep 14, 2023
5fc6b74
Update src/Resources/app/administration/src/module/frosh-mail-archive…
schneider-felix Sep 14, 2023
81e9731
Disable Link for current mail id
schneider-felix Sep 14, 2023
429c5e3
Disable link for current mail
schneider-felix Sep 14, 2023
14fe20d
Codestyle src/Services/MailSender.php
schneider-felix Sep 14, 2023
b331406
Codestyle src/Services/MailSender.php
schneider-felix Sep 14, 2023
a839bfe
Codestyle src/Services/MailSender.php
schneider-felix Sep 14, 2023
c7bdb4d
Change MailSender import
wirduzen-felix Sep 14, 2023
8090503
Symfony 6.2 compatibility
wirduzen-felix Sep 14, 2023
b9b2ae3
Merge main branch
wirduzen-felix Sep 14, 2023
34bc192
Fix PHPStan issues
wirduzen-felix Sep 14, 2023
78151df
feat: throw exception for missing mailId when determining sourceMailId
tinect Sep 15, 2023
36743a8
Merge remote-tracking branch 'origin/main' into failed-mails-storage
tinect Sep 15, 2023
65211e1
Add message queue compatibility
wirduzen-felix Oct 14, 2023
1f92250
Merge remote-tracking branch 'tinect/failed-mails-storage' into faile…
wirduzen-felix Oct 14, 2023
31ec45e
Add type check for mail id
wirduzen-felix Oct 14, 2023
e6c4265
Remove accidentally pushed composer.lock
wirduzen-felix Oct 14, 2023
044cc89
Remove accidentally pushed files
wirduzen-felix Oct 14, 2023
c961e27
Fix failed transport warning in mail archive list
wirduzen-felix Oct 14, 2023
03e83a5
Change order of drop table statements because of foreign key constraints
wirduzen-felix Oct 14, 2023
8dbe038
Remove messageId column
wirduzen-felix Oct 14, 2023
9622708
Update src/Subscriber/MailTransportSubscriber.php
schneider-felix Oct 14, 2023
7510e37
Update src/Services/MailSender.php
schneider-felix Oct 14, 2023
e76ad97
Save id header to archive
wirduzen-felix Oct 14, 2023
a3f4c25
Merge suggestions
wirduzen-felix Oct 14, 2023
ed6a97d
Remove sourcemap
wirduzen-felix Oct 14, 2023
b53d9b7
Remove empty translations
wirduzen-felix Oct 14, 2023
664df8c
Merge branch 'main' into failed-mails-storage
tinect Oct 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Content/MailArchive/MailArchiveDefinition.php
Expand Up @@ -4,6 +4,7 @@

use Shopware\Core\Checkout\Customer\CustomerDefinition;
use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition;
use Shopware\Core\Framework\DataAbstractionLayer\Field\BoolField;
use Shopware\Core\Framework\DataAbstractionLayer\Field\FkField;
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\AllowHtml;
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\CascadeDelete;
Expand Down Expand Up @@ -46,6 +47,7 @@ protected function defineFields(): FieldCollection
(new LongTextField('htmlText', 'htmlText'))->addFlags(new AllowHtml(), new SearchRanking(SearchRanking::LOW_SEARCH_RANKING)),
(new LongTextField('eml', 'eml'))->addFlags(new AllowHtml()),
(new StringField('eml_path', 'emlPath', 2048)),
(new BoolField('transport_failed', 'transportFailed'))->addFlags(new Required()),

(new OneToManyAssociationField('attachments', MailArchiveAttachmentDefinition::class, 'mail_archive_id', 'id'))->addFlags(new CascadeDelete()),

Expand All @@ -54,6 +56,9 @@ protected function defineFields(): FieldCollection

new FkField('customerId', 'customerId', CustomerDefinition::class),
new ManyToOneAssociationField('customer', 'customerId', CustomerDefinition::class, 'id', true),

new FkField('source_mail_id', 'sourceMailId', self::class),
new ManyToOneAssociationField('sourceMail', 'source_mail_id', self::class, 'id', false),
]);
}
}
37 changes: 37 additions & 0 deletions src/Content/MailArchive/MailArchiveEntity.php
Expand Up @@ -22,6 +22,8 @@ class MailArchiveEntity extends Entity

protected ?string $htmlText;

protected bool $transportFailed = false;

/**
* @deprecated will not be filled anyone. Use emlPath instead
*/
Expand All @@ -40,6 +42,10 @@ class MailArchiveEntity extends Entity
/** @var EntityCollection<MailArchiveAttachmentEntity>|null $attachments */
protected ?EntityCollection $attachments = null;

protected ?string $sourceMailId;

protected ?MailArchiveEntity $sourceMail;

public function getSender(): array
{
return $this->sender;
Expand Down Expand Up @@ -171,4 +177,35 @@ public function setAttachments(EntityCollection $attachments): void
{
$this->attachments = $attachments;
}

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

public function setTransportFailed(bool $transportFailed): void
{
$this->transportFailed = $transportFailed;
}

public function getSourceMailId(): ?string
{
return $this->sourceMailId;
}

public function setSourceMailId(?string $sourceMailId): void
{
$this->sourceMailId = $sourceMailId;
}

public function getSourceMail(): ?MailArchiveEntity
{
return $this->sourceMail;
}

public function setSourceMail(?MailArchiveEntity $sourceMail): void
{
$this->sourceMail = $sourceMail;
}

}
10 changes: 6 additions & 4 deletions src/Controller/Api/MailArchiveController.php
Expand Up @@ -6,13 +6,14 @@
use Frosh\MailArchive\Content\MailArchive\MailArchiveEntity;
use Frosh\MailArchive\Content\MailArchive\MailArchiveException;
use Frosh\MailArchive\Services\EmlFileManager;
use Frosh\MailArchive\Services\MailSender;
use Shopware\Core\Content\Mail\Service\AbstractMailSender;
use Shopware\Core\Content\Mail\Service\MailSender;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\PlatformRequest;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
Expand All @@ -30,13 +31,14 @@ class MailArchiveController extends AbstractController
public function __construct(
private readonly EntityRepository $froshMailArchiveRepository,
private readonly EntityRepository $froshMailArchiveAttachmentRepository,
private readonly MailSender $mailSender,
#[Autowire(service: MailSender::class)]
schneider-felix marked this conversation as resolved.
Show resolved Hide resolved
private readonly AbstractMailSender $mailSender,
private readonly RequestStack $requestStack,
private readonly EmlFileManager $emlFileManager
) {
}

#[Route(path: '/api/_action/frosh-mail-archive/resend-mail')]
#[Route(path: '/api/_action/frosh-mail-archive/resend-mail', name: 'api.action.frosh-mail-archive.resend-mail')]
public function resend(Request $request): JsonResponse
{
$mailId = $request->request->get('mailId');
Expand Down
25 changes: 25 additions & 0 deletions src/Migration/Migration1694519020TransportFailed.php
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Frosh\MailArchive\Migration;

use Doctrine\DBAL\Connection;
use Shopware\Core\Framework\Migration\MigrationStep;

class Migration1694519020TransportFailed extends MigrationStep
{
public function getCreationTimestamp(): int
{
return 1694519020;
}

public function update(Connection $connection): void
{
$connection->executeStatement('ALTER TABLE `frosh_mail_archive` ADD `transport_failed` TINYINT(1) NOT NULL DEFAULT 0;');
}

public function updateDestructive(Connection $connection): void
{
}
}
25 changes: 25 additions & 0 deletions src/Migration/Migration1694604822AddSourceMailId.php
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Frosh\MailArchive\Migration;

use Doctrine\DBAL\Connection;
use Shopware\Core\Framework\Migration\MigrationStep;

class Migration1694604822AddSourceMailId extends MigrationStep
{
public function getCreationTimestamp(): int
{
return 1694604822;
}

public function update(Connection $connection): void
{
$connection->executeStatement("ALTER TABLE `frosh_mail_archive` ADD `source_mail_id` BINARY(16) NULL;");
}

public function updateDestructive(Connection $connection): void
{
}
}
1 change: 1 addition & 0 deletions src/Resources/app/administration/src/main.js
@@ -1,3 +1,4 @@
import './init/api.init';
import './module/frosh-mail-archive';
import './component/notification-sw-admin';

@@ -0,0 +1,42 @@
<sw-card :title="$tc('frosh-mail-archive.detail.resend-grid.title')">
<template #grid>
<sw-data-grid
:isLoading="isLoading"
:data-source="resentMails"
:columns="columns"
:allowInlineEdit="false"
:allowColumnEdit="false"
:showSettings="false"
:showSelection="false"
>
<template #column-createdAt="{item}">
<router-link :to="{ name: 'frosh.mail.archive.detail', params: { id: item.id } }">
{{ item.createdAt|date }} <span v-if="currentMailId === item.id">({{ $tc('frosh-mail-archive.detail.resend-grid.currently-selected') }})</span>
</router-link>
schneider-felix marked this conversation as resolved.
Show resolved Hide resolved
</template>
<template #column-success="{item}">
<div v-if="!item.transportFailed">
<sw-color-badge
color="#37d046"
rounded
/>
{{ $tc('frosh-mail-archive.detail.resend-grid.success-label') }}
</div>
<div v-else>
<sw-color-badge
color="#de294c"
rounded
/>
{{ $tc('frosh-mail-archive.detail.resend-grid.failed-label') }}
</div>
</template>
<template #actions="{ item }">
<sw-context-menu-item
schneider-felix marked this conversation as resolved.
Show resolved Hide resolved
@click="navigateToDetailPage(item.id)"
>
{{ $tc('frosh-mail-archive.detail.resend-grid.navigate') }}
</sw-context-menu-item>
</template>
</sw-data-grid>
</template>
</sw-card>
@@ -0,0 +1,57 @@
const { Criteria } = Shopware.Data;
import template from './frosh-mail-resend-history.html.twig';

Shopware.Component.register('frosh-mail-resend-history', {
props: {
sourceMailId: {
required: true,
type: String
},
currentMailId: {
required: true,
type: String
}
},
template,
data() {
return {
resentMails: [],
isLoading: false,
columns: [{
property: 'createdAt',
label: this.$tc('frosh-mail-archive.detail.resend-grid.column-created-at'),
primary: true,
}, {
property: 'success',
label: this.$tc('frosh-mail-archive.detail.resend-grid.column-state'),
sortable: false,
}]
}
},
inject: ['repositoryFactory'],
computed: {
mailArchiveRepository() {
return this.repositoryFactory.create('frosh_mail_archive');
}
},
async created(){
this.isLoading = true;
await this.loadMails();
this.isLoading = false;
},
methods: {
async loadMails(){
const criteria = new Criteria();
criteria.addFilter(Criteria.multi('OR', [
Criteria.equals('id', this.sourceMailId),
Criteria.equals('sourceMailId', this.sourceMailId)
]));
criteria.addSorting(Criteria.sort('createdAt', 'DESC'));

this.resentMails = await this.mailArchiveRepository.search(criteria, Shopware.Context.api);
},
navigateToDetailPage(id){
this.$router.push({ name: 'frosh.mail.archive.detail', params: { id } })
}
}
});
@@ -1,5 +1,6 @@
import './page/frosh-mail-archive-index/index';
import './page/frosh-mail-archive-detail/index';
import './component/frosh-mail-resend-history'

Shopware.Module.register('frosh-mail-archive', {
type: 'plugin',
Expand All @@ -20,7 +21,12 @@ Shopware.Module.register('frosh-mail-archive', {
path: 'detail/:id',
meta: {
parentPath: 'frosh.mail.archive.list'
}
},
props: {
default: ($route) => {
return { archiveId: $route.params.id };
},
},
}
},

Expand Down
Expand Up @@ -9,3 +9,7 @@
white-space: pre-line;
}
}

.frosh-mail-archive__detail-alert {
max-width: 960px;
}
Expand Up @@ -8,17 +8,24 @@
{{ $tc('frosh-mail-archive.detail.toolbar.customer') }}
</sw-button>

<sw-button-process :isLoading="downloadIsLoading" :processSuccess="downloadIsSuccessful" @click="downloadMail">
<sw-button-process :isLoading="downloadIsLoading" :processSuccess="downloadIsSuccessful" @click="downloadMail" @process-finish="downloadFinish">
{{ $tc('frosh-mail-archive.detail.toolbar.downloadEml') }}
</sw-button-process>

<sw-button-process :isLoading="resendIsLoading" :processSuccess="resendIsSuccessful" @click="resendMail">
<sw-button-process :isLoading="resendIsLoading" :processSuccess="resendIsSuccessful" @click="resendMail" @process-finish="resendFinish">
{{ $tc('frosh-mail-archive.detail.toolbar.resend') }}
</sw-button-process>
</template>

<template slot="content">
<sw-card-view v-if="archive">
<sw-alert
v-if="archive.transportFailed"
schneider-felix marked this conversation as resolved.
Show resolved Hide resolved
variant="warning"
class="frosh-mail-archive__detail-alert"
>
{{ $tc('frosh-mail-archive.detail.alert.transportFailed') }}
</sw-alert>
<sw-card
:title="$tc('frosh-mail-archive.detail.metadata.title')"
position-identifier="frosh-mail-archive-metadata"
Expand All @@ -29,6 +36,7 @@
<sw-text-field :label="$tc('frosh-mail-archive.detail.metadata.subject')" :disabled="true" v-model="archive.subject"></sw-text-field>
<sw-text-field :label="$tc('frosh-mail-archive.detail.metadata.salesChannel')" v-if="archive.salesChannel" :disabled="true" v-model="archive.salesChannel.name"></sw-text-field>
</sw-card>
<frosh-mail-resend-history :key="resendKey" :currentMailId="archive.id" :sourceMailId="archive.sourceMailId ?? archive.id"/>
<sw-card
:title="$tc('frosh-mail-archive.detail.content.title')"
position-identifier="frosh-mail-archive-content"
Expand Down