getTo()) === 0) { throw new SendException('Invalid Message Parameter: MUST contain at least one TO address with a valid address'); } // validate that all To, CC and BCC have email address $entries = array_merge($message->getTo(), $message->getCc(), $message->getBcc()); array_walk($entries, function ($entry) { if (empty($entry->getAddress())) { throw new SendException('Invalid Message Parameter: All TO, CC and BCC addresses MUST contain at least an email address'); } }); // validate that all attachments have a name, type, and contents $entries = $message->getAttachments(); array_walk($entries, function ($entry) { if (empty($entry->getType()) || empty($entry->getContents())) { throw new SendException('Invalid Attachment Parameter: MUST contain values for Type and Contents'); } }); // retrieve user mail account details try { $account = $this->accountService->find($userId, (int)$serviceId); } catch (ClientException $e) { throw new SendException('Error: occurred while retrieving mail account details', 0, $e); } // convert mail provider message to mail app message $localMessage = new LocalMessage(); $localMessage->setType($localMessage::TYPE_OUTGOING); $localMessage->setAccountId($account->getId()); $localMessage->setSubject((string)$message->getSubject()); $localMessage->setBodyPlain($message->getBodyPlain()); $localMessage->setBodyHtml($message->getBodyHtml()); if (!empty($message->getBodyHtml())) { $localMessage->setHtml(true); } else { $localMessage->setHtml(false); } $localMessage->setSendAt($this->time->getTime()); // convert mail provider addresses to recipient addresses $to = $this->convertAddressArray($message->getTo()); $cc = $this->convertAddressArray($message->getCc()); $bcc = $this->convertAddressArray($message->getBcc()); // save attachments $attachments = []; try { foreach ($message->getAttachments() as $entry) { $attachments[] = $this->attachmentService->addFileFromString( $userId, (string)$entry->getName(), (string)$entry->getType(), (string)$entry->getContents() ); } } catch (UploadException $e) { $this->purgeSavedAttachments($attachments); throw new SendException('Error: occurred while saving mail message attachment', 0, $e); } // save message $localMessage = $this->outboxService->saveMessage( $account, $localMessage, $to, $cc, $bcc, array_map(static fn (LocalAttachment $attachment) => $attachment->jsonSerialize(), $attachments) ); // send message try { $localMessage = $this->outboxService->sendMessage($localMessage, $account); } catch (\Throwable $e) { throw new SendException('Error: occurred while sending mail message', 0, $e); } return $localMessage; } /** * Converts IAddress objects collection to plain array * * @since 4.0.0 * * @param array $addresses collection of IAddress objects * * @return array collection of addresses and labels */ protected function convertAddressArray(array $addresses): array { return array_map(static fn (IAddress $address) => !empty($address->getLabel()) ? ['email' => (string)$address->getAddress(), 'label' => (string)$address->getLabel()] : ['email' => (string)$address->getAddress()], $addresses); } /** * Removes attachments from data store * * @since 4.0.0 * * @param array $attachments collection of local attachment objects */ protected function purgeSavedAttachments(array $attachments): void { foreach ($attachments as $attachment) { $this->attachmentService->deleteAttachment($attachment->getUserId(), $attachment->getId()); } } }