Skip to content

Commit

Permalink
revert(outbox): catch failed SENT copy operation
Browse files Browse the repository at this point in the history
Signed-off-by: Christoph Wurst <[email protected]>
  • Loading branch information
ChristophWurst committed Apr 12, 2024
1 parent 504f71e commit 5980dc4
Show file tree
Hide file tree
Showing 58 changed files with 2,184 additions and 2,720 deletions.
2 changes: 1 addition & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ The rating depends on the installed text processing backend. See [the rating ove
Learn more about the Nextcloud Ethical AI Rating [in our blog](https://nextcloud.com/blog/nextcloud-ethical-ai-rating/).
]]></description>
<version>3.6.0-rc.2</version>
<version>3.6.0-rc.3</version>
<licence>agpl</licence>
<author>Christoph Wurst</author>
<author homepage="https://github.com/nextcloud/groupware">Nextcloud Groupware Team</author>
Expand Down
7 changes: 7 additions & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
use OCA\Mail\Dashboard\UnreadMailWidget;
use OCA\Mail\Dashboard\UnreadMailWidgetV2;
use OCA\Mail\Events\BeforeImapClientCreated;
use OCA\Mail\Events\BeforeMessageSentEvent;
use OCA\Mail\Events\DraftMessageCreatedEvent;
use OCA\Mail\Events\DraftSavedEvent;
use OCA\Mail\Events\MailboxesSynchronizedEvent;
Expand All @@ -54,7 +55,9 @@
use OCA\Mail\Http\Middleware\ProvisioningMiddleware;
use OCA\Mail\Listener\AccountSynchronizedThreadUpdaterListener;
use OCA\Mail\Listener\AddressCollectionListener;
use OCA\Mail\Listener\AntiAbuseListener;
use OCA\Mail\Listener\DeleteDraftListener;
use OCA\Mail\Listener\FlagRepliedMessageListener;
use OCA\Mail\Listener\HamReportListener;
use OCA\Mail\Listener\InteractionListener;
use OCA\Mail\Listener\MailboxesSynchronizedSpecialMailboxesUpdater;
Expand All @@ -65,6 +68,7 @@
use OCA\Mail\Listener\OauthTokenRefreshListener;
use OCA\Mail\Listener\OptionalIndicesListener;
use OCA\Mail\Listener\OutOfOfficeListener;
use OCA\Mail\Listener\SaveSentMessageListener;
use OCA\Mail\Listener\SpamReportListener;
use OCA\Mail\Listener\UserDeletedListener;
use OCA\Mail\Notification\Notifier;
Expand Down Expand Up @@ -128,6 +132,7 @@ public function register(IRegistrationContext $context): void {

$context->registerEventListener(AddMissingIndicesEvent::class, OptionalIndicesListener::class);
$context->registerEventListener(BeforeImapClientCreated::class, OauthTokenRefreshListener::class);
$context->registerEventListener(BeforeMessageSentEvent::class, AntiAbuseListener::class);
$context->registerEventListener(DraftSavedEvent::class, DeleteDraftListener::class);
$context->registerEventListener(DraftMessageCreatedEvent::class, DeleteDraftListener::class);
$context->registerEventListener(OutboxMessageCreatedEvent::class, DeleteDraftListener::class);
Expand All @@ -138,7 +143,9 @@ public function register(IRegistrationContext $context): void {
$context->registerEventListener(MessageFlaggedEvent::class, MoveJunkListener::class);
$context->registerEventListener(MessageDeletedEvent::class, MessageCacheUpdaterListener::class);
$context->registerEventListener(MessageSentEvent::class, AddressCollectionListener::class);
$context->registerEventListener(MessageSentEvent::class, FlagRepliedMessageListener::class);
$context->registerEventListener(MessageSentEvent::class, InteractionListener::class);
$context->registerEventListener(MessageSentEvent::class, SaveSentMessageListener::class);
$context->registerEventListener(NewMessagesSynchronized::class, NewMessageClassificationListener::class);
$context->registerEventListener(NewMessagesSynchronized::class, MessageKnownSinceListener::class);
$context->registerEventListener(SynchronizationEvent::class, AccountSynchronizedThreadUpdaterListener::class);
Expand Down
2 changes: 1 addition & 1 deletion lib/BackgroundJob/QuotaJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ protected function run($argument): void {
}

$quota = $this->mailManager->getQuota($account);
if ($quota === null) {
if($quota === null) {
$this->logger->debug('Could not get quota information for account <' . $account->getEmail() . '>', ['app' => 'mail']);
return;
}
Expand Down
22 changes: 19 additions & 3 deletions lib/Contracts/IMailTransmission.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
namespace OCA\Mail\Contracts;

use OCA\Mail\Account;
use OCA\Mail\Db\Alias;
use OCA\Mail\Db\LocalMessage;
use OCA\Mail\Db\Mailbox;
use OCA\Mail\Db\Message;
Expand All @@ -36,12 +37,27 @@ interface IMailTransmission {
/**
* Send a new message or reply to an existing one
*
* @param Account $account
* @param LocalMessage $localMessage
* @param NewMessageData $messageData
* @param string|null $repliedToMessageId
* @param Alias|null $alias
* @param Message|null $draft
*
* @throws SentMailboxNotSetException
* @throws ServiceException
*/
public function sendMessage(Account $account, LocalMessage $localMessage): void;
public function sendMessage(NewMessageData $messageData,
?string $repliedToMessageId = null,
?Alias $alias = null,
?Message $draft = null): void;

/**
* @param Account $account
* @param LocalMessage $message
* @throws ClientException
* @throws ServiceException
* @return void
*/
public function sendLocalMessage(Account $account, LocalMessage $message): void;

/**
* @param Account $account
Expand Down
1 change: 1 addition & 0 deletions lib/Controller/DraftsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ public function update(int $id,
$message = $this->service->getMessage($id, $this->userId);
$account = $this->accountService->find($this->userId, $accountId);


$message->setType(LocalMessage::TYPE_DRAFT);
$message->setAccountId($accountId);
$message->setAliasId($aliasId);
Expand Down
14 changes: 4 additions & 10 deletions lib/Controller/OutboxController.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public function createFromDraft(DraftsService $draftsService, int $id, ?int $sen

$outboxMessage = $this->service->convertDraft($draftMessage, $sendAt);

return JsonResponse::success(
return JsonResponse::success(
$outboxMessage,
Http::STATUS_CREATED,
);
Expand Down Expand Up @@ -209,9 +209,6 @@ public function update(
?int $sendAt = null
): JsonResponse {
$message = $this->service->getMessage($id, $this->userId);
if ($message->getStatus() === LocalMessage::STATUS_PROCESSED) {
return JsonResponse::error('Cannot modify already sent message', Http::STATUS_FORBIDDEN, [$message]);
}
$account = $this->accountService->find($this->userId, $accountId);

$message->setAccountId($accountId);
Expand All @@ -220,6 +217,7 @@ public function update(
$message->setBody($body);
$message->setEditorBody($editorBody);
$message->setHtml($isHtml);
$message->setFailed($failed);
$message->setInReplyToMessageId($inReplyToMessageId);
$message->setSendAt($sendAt);
$message->setSmimeSign($smimeSign);
Expand All @@ -246,12 +244,8 @@ public function send(int $id): JsonResponse {
$message = $this->service->getMessage($id, $this->userId);
$account = $this->accountService->find($this->userId, $message->getAccountId());

$message = $this->service->sendMessage($message, $account);

if($message->getStatus() !== LocalMessage::STATUS_PROCESSED) {
return JsonResponse::error('Could not send message', Http::STATUS_INTERNAL_SERVER_ERROR, [$message]);
}
return JsonResponse::success(
$this->service->sendMessage($message, $account);
return JsonResponse::success(
'Message sent', Http::STATUS_ACCEPTED
);
}
Expand Down
31 changes: 1 addition & 30 deletions lib/Db/LocalMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,30 +60,13 @@
* @method setSmimeCertificateId(?int $smimeCertificateId)
* @method bool|null getSmimeEncrypt()
* @method setSmimeEncrypt (bool $smimeEncryt)
* @method int|null getStatus();
* @method setStatus(?int $status);
* @method string|null getRaw()
* @method setRaw(string|null $raw)
*/
class LocalMessage extends Entity implements JsonSerializable {
public const TYPE_OUTGOING = 0;
public const TYPE_DRAFT = 1;

public const STATUS_RAW = 0;
public const STATUS_NO_SENT_MAILBOX = 1;
public const STATUS_SMIME_SIGN_NO_CERT_ID = 2;
public const STATUS_SMIME_SIGN_CERT = 3;
public const STATUS_SMIME_SIGN_FAIL = 4;
public const STATUS_SMIME_ENCRYPT_NO_CERT_ID = 5;
public const STATUS_SMIME_ENCRYPT_CERT = 6;
public const STATUS_SMIME_ENCRYT_FAIL = 7;
public const STATUS_TOO_MANY_RECIPIENTS = 8;
public const STATUS_RATELIMIT = 9;
public const STATUS_SMPT_SEND_FAIL = 10;
public const STATUS_IMAP_SENT_MAILBOX_FAIL = 11;
public const STATUS_PROCESSED = 12;
/**
* @var int<1,12>
* @var int
* @psalm-var self::TYPE_*
*/
protected $type;
Expand Down Expand Up @@ -133,15 +116,6 @@ class LocalMessage extends Entity implements JsonSerializable {
/** @var bool|null */
protected $smimeEncrypt;

/**
* @var int|null
* @psalm-var int-mask-of<self::STATUS_*>
*/
protected $status;

/** @var string|null */
protected $raw;

public function __construct() {
$this->addType('type', 'integer');
$this->addType('accountId', 'integer');
Expand All @@ -153,7 +127,6 @@ public function __construct() {
$this->addType('smimeSign', 'boolean');
$this->addType('smimeCertificateId', 'integer');
$this->addType('smimeEncrypt', 'boolean');
$this->addType('status', 'integer');
}

#[ReturnTypeWillChange]
Expand Down Expand Up @@ -195,8 +168,6 @@ public function jsonSerialize() {
'smimeCertificateId' => $this->getSmimeCertificateId(),
'smimeSign' => $this->getSmimeSign() === true,
'smimeEncrypt' => $this->getSmimeEncrypt() === true,
'status' => $this->getStatus(),
'raw' => $this->getRaw(),
];
}

Expand Down
7 changes: 5 additions & 2 deletions lib/Db/LocalMessageMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ public function getAllForUser(string $userId, int $type = LocalMessage::TYPE_OUT
->join('a', $this->getTableName(), 'm', $qb->expr()->eq('m.account_id', 'a.id'))
->where(
$qb->expr()->eq('a.user_id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR), IQueryBuilder::PARAM_STR),
$qb->expr()->eq('m.type', $qb->createNamedParameter($type, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT),
$qb->expr()->neq('m.status', $qb->createNamedParameter(LocalMessage::STATUS_PROCESSED, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT)
$qb->expr()->eq('m.type', $qb->createNamedParameter($type, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT)
);
$rows = $qb->executeQuery();

Expand Down Expand Up @@ -135,6 +134,10 @@ public function findDue(int $time, int $type = LocalMessage::TYPE_OUTGOING): arr
$qb->expr()->isNotNull('send_at'),
$qb->expr()->eq('type', $qb->createNamedParameter($type, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT),
$qb->expr()->lte('send_at', $qb->createNamedParameter($time, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT),
$qb->expr()->orX(
$qb->expr()->isNull('failed'),
$qb->expr()->eq('failed', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL), IQueryBuilder::PARAM_BOOL),
)
)
->orderBy('send_at', 'asc');
$messages = $this->findEntities($select);
Expand Down
95 changes: 95 additions & 0 deletions lib/Events/BeforeMessageSentEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

declare(strict_types=1);

/*
* @copyright 2021 Christoph Wurst <[email protected]>
*
* @author 2021 Christoph Wurst <[email protected]>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

namespace OCA\Mail\Events;

use Horde_Mime_Mail;
use OCA\Mail\Account;
use OCA\Mail\Db\Message;
use OCA\Mail\Model\IMessage;
use OCA\Mail\Model\NewMessageData;
use OCP\EventDispatcher\Event;

/**
* @psalm-immutable
*/
class BeforeMessageSentEvent extends Event {
/** @var Account */
private $account;

/** @var NewMessageData */
private $newMessageData;

/** @var Message|null */
private $draft;

/** @var IMessage */
private $message;

/** @var Horde_Mime_Mail */
private $mail;

/** @var string|null */
private $repliedToMessageId;

public function __construct(Account $account,
NewMessageData $newMessageData,
?string $repliedToMessageId,
?Message $draft,
IMessage $message,
Horde_Mime_Mail $mail) {
parent::__construct();
$this->account = $account;
$this->newMessageData = $newMessageData;
$this->repliedToMessageId = $repliedToMessageId;
$this->draft = $draft;
$this->message = $message;
$this->mail = $mail;
}

public function getAccount(): Account {
return $this->account;
}

public function getNewMessageData(): NewMessageData {
return $this->newMessageData;
}

public function getRepliedToMessageId(): ?string {
return $this->repliedToMessageId;
}

public function getDraft(): ?Message {
return $this->draft;
}

public function getMessage(): IMessage {
return $this->message;
}

public function getMail(): Horde_Mime_Mail {
return $this->mail;
}
}
8 changes: 4 additions & 4 deletions lib/Events/DraftSavedEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ class DraftSavedEvent extends Event {
/** @var Account */
private $account;

/** @var NewMessageData|null */
/** @var NewMessageData */
private $newMessageData;

/** @var Message|null */
private $draft;

public function __construct(Account $account,
?NewMessageData $newMessageData = null,
?Message $draft = null) {
NewMessageData $newMessageData,
?Message $draft) {
parent::__construct();
$this->account = $account;
$this->newMessageData = $newMessageData;
Expand All @@ -53,7 +53,7 @@ public function getAccount(): Account {
return $this->account;
}

public function getNewMessageData(): ?NewMessageData {
public function getNewMessageData(): NewMessageData {
return $this->newMessageData;
}

Expand Down
Loading

0 comments on commit 5980dc4

Please sign in to comment.