@@ -1593,7 +1593,7 @@ public function importMessagingResource(Resource $resource): Resource
15931593 * @throws AppwriteException
15941594 * @throws \Exception
15951595 */
1596- protected function createProvider (Provider $ resource ): void
1596+ protected function createProvider (Provider $ resource ): bool
15971597 {
15981598 $ credentials = $ resource ->getCredentials ();
15991599 $ options = $ resource ->getOptions ();
@@ -1608,50 +1608,50 @@ protected function createProvider(Provider $resource): void
16081608 $ credentials ['apiKey ' ] ?? null ,
16091609 $ credentials ['domain ' ] ?? null ,
16101610 $ credentials ['isEuRegion ' ] ?? null ,
1611- $ options ['fromName ' ] ?? null ,
1612- $ options ['fromEmail ' ] ?? null ,
1613- $ options ['replyToName ' ] ?? null ,
1614- $ options ['replyToEmail ' ] ?? null ,
1611+ $ options ['fromName ' ] ?: null ,
1612+ $ options ['fromEmail ' ] ?: null ,
1613+ $ options ['replyToName ' ] ?: null ,
1614+ $ options ['replyToEmail ' ] ?: null ,
16151615 $ enabled ,
16161616 ),
16171617 'sendgrid ' => $ this ->messaging ->createSendgridProvider (
16181618 $ id ,
16191619 $ name ,
16201620 $ credentials ['apiKey ' ] ?? null ,
1621- $ options ['fromName ' ] ?? null ,
1622- $ options ['fromEmail ' ] ?? null ,
1623- $ options ['replyToName ' ] ?? null ,
1624- $ options ['replyToEmail ' ] ?? null ,
1621+ $ options ['fromName ' ] ?: null ,
1622+ $ options ['fromEmail ' ] ?: null ,
1623+ $ options ['replyToName ' ] ?: null ,
1624+ $ options ['replyToEmail ' ] ?: null ,
16251625 $ enabled ,
16261626 ),
16271627 'resend ' => $ this ->messaging ->createResendProvider (
16281628 $ id ,
16291629 $ name ,
16301630 $ credentials ['apiKey ' ] ?? null ,
1631- $ options ['fromName ' ] ?? null ,
1632- $ options ['fromEmail ' ] ?? null ,
1633- $ options ['replyToName ' ] ?? null ,
1634- $ options ['replyToEmail ' ] ?? null ,
1631+ $ options ['fromName ' ] ?: null ,
1632+ $ options ['fromEmail ' ] ?: null ,
1633+ $ options ['replyToName ' ] ?: null ,
1634+ $ options ['replyToEmail ' ] ?: null ,
16351635 $ enabled ,
16361636 ),
16371637 'smtp ' => $ this ->messaging ->createSMTPProvider (
16381638 $ id ,
16391639 $ name ,
16401640 $ credentials ['host ' ] ?? '' ,
16411641 $ credentials ['port ' ] ?? null ,
1642- $ credentials ['username ' ] ?? null ,
1643- $ credentials ['password ' ] ?? null ,
1642+ $ credentials ['username ' ] ?: null ,
1643+ $ credentials ['password ' ] ?: null ,
16441644 match ($ options ['encryption ' ] ?? '' ) {
16451645 'ssl ' => SmtpEncryption::SSL (),
16461646 'tls ' => SmtpEncryption::TLS (),
16471647 default => SmtpEncryption::NONE (),
16481648 },
16491649 $ options ['autoTLS ' ] ?? null ,
16501650 $ options ['mailer ' ] ?: null ,
1651- $ options ['fromName ' ] ?? null ,
1652- $ options ['fromEmail ' ] ?? null ,
1653- $ options ['replyToName ' ] ?? null ,
1654- $ options ['replyToEmail ' ] ?? null ,
1651+ $ options ['fromName ' ] ?: null ,
1652+ $ options ['fromEmail ' ] ?: null ,
1653+ $ options ['replyToName ' ] ?: null ,
1654+ $ options ['replyToEmail ' ] ?: null ,
16551655 $ enabled ,
16561656 ),
16571657 'msg91 ' => $ this ->messaging ->createMsg91Provider (
@@ -1665,31 +1665,31 @@ protected function createProvider(Provider $resource): void
16651665 'telesign ' => $ this ->messaging ->createTelesignProvider (
16661666 $ id ,
16671667 $ name ,
1668- $ options ['from ' ] ?? null ,
1668+ $ options ['from ' ] ?: null ,
16691669 $ credentials ['customerId ' ] ?? null ,
16701670 $ credentials ['apiKey ' ] ?? null ,
16711671 $ enabled ,
16721672 ),
16731673 'textmagic ' => $ this ->messaging ->createTextmagicProvider (
16741674 $ id ,
16751675 $ name ,
1676- $ options ['from ' ] ?? null ,
1676+ $ options ['from ' ] ?: null ,
16771677 $ credentials ['username ' ] ?? null ,
16781678 $ credentials ['apiKey ' ] ?? null ,
16791679 $ enabled ,
16801680 ),
16811681 'twilio ' => $ this ->messaging ->createTwilioProvider (
16821682 $ id ,
16831683 $ name ,
1684- $ options ['from ' ] ?? null ,
1684+ $ options ['from ' ] ?: null ,
16851685 $ credentials ['accountSid ' ] ?? null ,
16861686 $ credentials ['authToken ' ] ?? null ,
16871687 $ enabled ,
16881688 ),
16891689 'vonage ' => $ this ->messaging ->createVonageProvider (
16901690 $ id ,
16911691 $ name ,
1692- $ options ['from ' ] ?? null ,
1692+ $ options ['from ' ] ?: null ,
16931693 $ credentials ['apiKey ' ] ?? null ,
16941694 $ credentials ['apiSecret ' ] ?? null ,
16951695 $ enabled ,
@@ -1712,50 +1712,105 @@ protected function createProvider(Provider $resource): void
17121712 ),
17131713 default => throw new \Exception ('Unknown provider: ' . $ resource ->getProvider ()),
17141714 };
1715+
1716+ return true ;
17151717 }
17161718
17171719 /**
17181720 * @throws AppwriteException
17191721 * @throws \Exception
17201722 */
1721- protected function createMessage (Message $ resource ): void
1723+ protected function createMessage (Message $ resource ): bool
1724+ {
1725+ $ resolvedTargets = $ this ->resolveMessageTargets ($ resource );
1726+ $ status = $ resource ->getMessageStatus ();
1727+
1728+ // Use SDK for scheduled messages so the platform schedule document is created.
1729+ // Fall back to draft if scheduledAt is missing or in the past.
1730+ if ($ status === 'scheduled ' ) {
1731+ $ scheduledAt = $ resource ->getScheduledAt ();
1732+
1733+ if (!empty ($ scheduledAt ) && new \DateTime ($ scheduledAt ) > new \DateTime ()) {
1734+ return $ this ->createScheduledMessage ($ resource , $ resolvedTargets );
1735+ }
1736+
1737+ $ status = 'draft ' ;
1738+ }
1739+
1740+ // Processing messages have no worker on the destination, import as draft.
1741+ if ($ status === 'processing ' ) {
1742+ $ status = 'draft ' ;
1743+ }
1744+
1745+ $ createdAt = $ this ->normalizeDateTime ($ resource ->getCreatedAt ());
1746+ $ updatedAt = $ this ->normalizeDateTime ($ resource ->getUpdatedAt (), $ createdAt );
1747+
1748+ $ this ->database ->createDocument ('messages ' , new UtopiaDocument ([
1749+ '$id ' => $ resource ->getId (),
1750+ '$createdAt ' => $ createdAt ,
1751+ '$updatedAt ' => $ updatedAt ,
1752+ 'providerType ' => $ resource ->getProviderType (),
1753+ 'topics ' => $ resource ->getTopics (),
1754+ 'users ' => $ resource ->getUsers (),
1755+ 'targets ' => $ resolvedTargets ,
1756+ 'scheduledAt ' => null ,
1757+ 'deliveredAt ' => $ resource ->getDeliveredAt () ?: null ,
1758+ 'deliveryErrors ' => $ resource ->getDeliveryErrors (),
1759+ 'deliveredTotal ' => $ resource ->getDeliveredTotal (),
1760+ 'data ' => $ resource ->getData (),
1761+ 'status ' => $ status ,
1762+ ]));
1763+
1764+ return true ;
1765+ }
1766+
1767+ /**
1768+ * Create a scheduled message via SDK so the platform schedule document is created.
1769+ *
1770+ * @param array<string> $resolvedTargets
1771+ * @throws AppwriteException
1772+ * @throws \Exception
1773+ */
1774+ protected function createScheduledMessage (Message $ resource , array $ resolvedTargets ): bool
17221775 {
1723- $ id = $ resource ->getId ();
17241776 $ data = $ resource ->getData ();
17251777 $ topics = $ resource ->getTopics () ?: null ;
17261778 $ users = $ resource ->getUsers () ?: null ;
1727- $ targets = $ resource ->getTargets () ?: null ;
1779+ $ targets = $ resolvedTargets ?: null ;
1780+ $ scheduledAt = $ resource ->getScheduledAt ();
17281781
17291782 match ($ resource ->getProviderType ()) {
17301783 'email ' => $ this ->messaging ->createEmail (
1731- $ id ,
1784+ $ resource -> getId () ,
17321785 $ data ['subject ' ] ?? '' ,
17331786 $ data ['content ' ] ?? '' ,
17341787 $ topics ,
17351788 $ users ,
17361789 $ targets ,
1737- ! empty ( $ data ['cc ' ]) ? $ data [ ' cc ' ] : null ,
1738- ! empty ( $ data ['bcc ' ]) ? $ data [ ' bcc ' ] : null ,
1790+ $ data ['cc ' ] ?? null ,
1791+ $ data ['bcc ' ] ?? null ,
17391792 null ,
17401793 false ,
17411794 $ data ['html ' ] ?? null ,
1795+ $ scheduledAt ,
17421796 ),
17431797 'sms ' => $ this ->messaging ->createSMS (
1744- $ id ,
1798+ $ resource -> getId () ,
17451799 $ data ['content ' ] ?? '' ,
17461800 $ topics ,
17471801 $ users ,
17481802 $ targets ,
17491803 false ,
1804+ $ scheduledAt ,
17501805 ),
17511806 'push ' => $ this ->messaging ->createPush (
1752- $ id ,
1807+ $ resource -> getId () ,
17531808 $ data ['title ' ] ?? null ,
17541809 $ data ['body ' ] ?? null ,
17551810 $ topics ,
17561811 $ users ,
17571812 $ targets ,
1758- ! empty ( $ data ['data ' ]) ? $ data [ ' data ' ] : null ,
1813+ $ data ['data ' ] ?? null ,
17591814 $ data ['action ' ] ?? null ,
17601815 $ data ['image ' ] ?? null ,
17611816 $ data ['icon ' ] ?? null ,
@@ -1764,9 +1819,49 @@ protected function createMessage(Message $resource): void
17641819 $ data ['tag ' ] ?? null ,
17651820 $ data ['badge ' ] ?? null ,
17661821 false ,
1822+ $ scheduledAt ,
1823+ $ data ['contentAvailable ' ] ?? null ,
1824+ $ data ['critical ' ] ?? null ,
1825+ null ,
17671826 ),
1768- default => throw new \Exception ('Unknown message provider type: ' . $ resource ->getProviderType ()),
1827+ default => throw new \Exception ('Unknown provider type: ' . $ resource ->getProviderType ()),
17691828 };
1829+
1830+ return true ;
1831+ }
1832+
1833+ /**
1834+ * Resolve source target IDs to destination target IDs for a message.
1835+ *
1836+ * @return array<string>
1837+ */
1838+ private function resolveMessageTargets (Message $ resource ): array
1839+ {
1840+ $ targetUserMap = $ resource ->getTargetUserMap ();
1841+ $ providerType = $ resource ->getProviderType ();
1842+ $ resolvedTargets = [];
1843+ $ targetCache = [];
1844+
1845+ foreach ($ resource ->getTargets () as $ sourceTargetId ) {
1846+ $ userId = $ targetUserMap [$ sourceTargetId ] ?? null ;
1847+
1848+ if ($ userId === null ) {
1849+ continue ;
1850+ }
1851+
1852+ if (!isset ($ targetCache [$ userId ])) {
1853+ $ targetCache [$ userId ] = $ this ->users ->listTargets ($ userId );
1854+ }
1855+
1856+ foreach ($ targetCache [$ userId ]['targets ' ] as $ target ) {
1857+ if ($ target ['providerType ' ] === $ providerType ) {
1858+ $ resolvedTargets [] = $ target ['$id ' ];
1859+ break ;
1860+ }
1861+ }
1862+ }
1863+
1864+ return $ resolvedTargets ;
17701865 }
17711866
17721867 /**
@@ -1775,7 +1870,7 @@ protected function createMessage(Message $resource): void
17751870 * User targets are auto-generated on the destination with new IDs,
17761871 * so we look up the matching target by userId and providerType.
17771872 */
1778- protected function resolveTargetId (Subscriber $ resource ): string
1873+ private function resolveTargetId (Subscriber $ resource ): string
17791874 {
17801875 $ response = $ this ->users ->listTargets ($ resource ->getUserId ());
17811876
0 commit comments