v13.39.0. Zie E-mail versturen voor de basis van het versturen en Packageontwikkeling voor het voorbereiden van de provider.
Scheid de Mailernaam van de Transportnaam
Mail::mailer('receipts') leest mail.mailers.receipts en roept de aanmaakfunctie aan die bij transport hoort. MailManager::build() geeft die Transport door aan de Mailer van Laravel en stelt bij normaal resolven op naam ook onder meer de globale afzender in.
Eigen aanmaakfuncties krijgen voorrang op de ingebouwde Transports. Overschrijf smtp of ses dus niet, maar gebruik een packagespecifieke Transportnaam.
Bouw het registratiepad zonder externe verzending
Controleer eerst de configuratie en het resolvepad in plaats van de API van de bezorgdienst. Maak insrc/Transport/MemoryTransport.php van het package Acme\Postbox een klasse die de standaard ArrayTransport uitbreidt.
ArrayTransport::send() slaat de SentMessage van Symfony op in een interne Collection. Je kunt die bekijken met messages() en met flush() wis je de vastgelegde berichten van die instantie. Het label dient om te controleren dat de configuratie de aanmaakfunctie heeft bereikt.
Registreer bij de lazy geladen Manager
De officiële documentatie roeptMail::extend() aan in boot(). In een package kun je dit combineren met een hook na het resolven van een service, zodat applicaties die geen e-mail gebruiken de Manager niet onnodig aanmaken.
Maak src/PostboxServiceProvider.php aan.
- De
MailServiceProvidervan Laravel is een deferred provider en registreertmail.managerals singleton. DeMail-facade resolvet ook deze key. callAfterResolving()wacht op een latere resolve als de Manager nog niet is geresolved, en past de uitbreiding direct toe op een al geresolvede Manager. Al aangemaakte Mailers worden hiermee niet vervangen.- Maak je eigen provider die de uitbreiding registreert niet zomaar een
DeferrableProvider. Zorg ervoor dat je eigen Transport niet wordt opgevraagd voordat de hook is geregistreerd. - Dit voorbeeld registreert de hook in de eigen
boot(). Een opstartvolgorde waarin andere providers de eigen Mailer al eerder gebruiken, wordt niet gegarandeerd. Ontwerp de registratievolgorde en verstuur geen e-mail binnenregister().
Verwar de argumenten van extend niet met die van andere Managers
MailManager::createSymfonyTransport() roept een eigen aanmaakfunctie aan met slechts één configuratie-array. Het zijn niet de twee argumenten applicatie en configuratie zoals bij Cache::extend(). De returnwaarde is een Transport die TransportInterface implementeert, geen Laravel-Mailer of verzendresultaat.
Bovendien slaat MailManager::extend() de closure alleen op en bindt die niet opnieuw aan de Manager. Het voorbeeld gebruikt een statische closure en expliciete argumenten, zodat het niet afhankelijk is van hoe $this wordt geïnterpreteerd.
Heb je een client voor een externe API nodig, pas dan in deze aanmaakfunctie de configuratie toe en geef die door aan de Transport. Verstuur niets op het moment van registreren, en ontwerp het zo dat configuratie en bestemmingen niet door elkaar raken wanneer meerdere Mailers dezelfde Transportnaam gebruiken.
Voeg Mailers toe in de gebruikende applicatie
Voeg de volgende twee toe aan de bestaandemailers-array in config/mail.php. Overschrijf vanuit het package niet de standaardwaarde of de volledige mailers van de gebruiker.
MAIL_MAILER niet de Transportnaam op, maar de Mailernaam receipts. Met een expliciete keuze per aanroep kun je het gebruiken zonder de bestaande standaard te wijzigen.
raw() is een voorbeeld om het synchrone verzendpad te controleren zonder een view voor te bereiden. Ook bij normaal versturen met een Mailable genereert de Mailer eerst de inhoud en geeft die daarna door aan dezelfde Transport.
Grenzen bij het bouwen van een echte bezorg-Transport
Voor een implementatie die naar een externe dienst bezorgt, kun je volgens de officiële documentatieSymfony\Component\Mailer\Transport\AbstractTransport uitbreiden en doSend(SentMessage $message): void en __toString(): string implementeren. De registratiemethode hierboven kun je ongewijzigd gebruiken.
Mailer::sendSymfonyMessage() van Laravel roept send() van de Transport aan. Als een MessageSending-listener het verzenden afbreekt of de Transport null retourneert, retourneert ook send() van Laravel geen verzendresultaat. Beschouw het uitblijven van een exception niet als enig bewijs van geslaagde bezorging. Ook als er een SentMessage terugkomt, is dat geen garantie dat het bericht de mailbox van de ontvanger heeft bereikt.
Onderscheid configuratiewijzigingen van het opnieuw resolven van Mailers
MailManager houdt Mailers en hun Transport per Mailernaam vast. Alleen de configuratie wijzigen of extend() opnieuw registreren werkt al aangemaakte objecten niet bij.
$same is dezelfde Mailer als $before. Bij $after, die na purge('receipts') wordt opgehaald, wordt de Transport aangemaakt op basis van de nieuwe configuratie.
De gecontroleerde implementatie van
purge() verwijdert alleen de referentie uit de interne array van de Manager. De oude $before en services waarin die Mailer al is geïnjecteerd, worden niet vervangen. Het sluit ook niet expliciet externe verbindingen af.
Bovenliggende Mailers zoals failover worden apart vastgehouden
failover en roundrobin lezen de configuratie van de onderliggende Mailernamen, maken de Transports rechtstreeks aan en nemen ze op in de Transport van de bovenliggende Mailer. Ze delen geen instanties van Mail::mailer() van de onderliggende Mailers.
Wijzig je daarom de configuratie van een onderliggende Mailer en roep je purge('receipts') aan, dan wordt de interne Transport van een al geresolvede bovenliggende Mailer niet bijgewerkt. Ook de betreffende bovenliggende Mailer moet opnieuw worden geresolved. Zelfs forgetMailers() kan referenties naar bovenliggende Mailers die de gebruikende code al vasthoudt niet vervangen.
Neem in productie het vernieuwen van de configuratiecache en het herstarten van langlevende workers op in je normale deployproces. Zie opnieuw resolven niet als een gelijktijdige update van alle processen, en lees ook Levensduur van services.
Test niet alleen met Mail::fake, maar ook het echte aanmaakpad
Mail::fake() dient om het versturen en in de queue plaatsen van Mailables vast te leggen. MailFake::mailer() resolvet geen echte Mailer, maar legt de Mailernaam vast en retourneert de fake zelf. Ook raw() verstuurt niets. Assertions voor verzonden Mailables kunnen dus slagen, zelfs als je eigen Transport niet is geregistreerd.
Laat in de testomgeving van het package zoals hieronder de echte Manager en Transport doorlopen, zonder fake. De Transport in dit voorbeeld verstuurt niets naar buiten, zodat je het registratiepad zonder risico op echte bezorging kunt controleren. Er wordt eerst een hulpprovider geladen, zodat ook het geval van een al geresolvede Manager wordt geverifieerd.
Geraadpleegde primaire bronnen
- Officiële Laravel-documentatie: eigen Transports en testen voor e-mail (op het moment van controle)
- Officiële Laravel-documentatie: packageontwikkeling
- MailManager: aanmaken, vasthouden van Mailers, purge en samengestelde Transports
- MailServiceProvider: binding van de MailManager
- ServiceProvider: callAfterResolving
- Mailer: versturen naar de Transport en events
- ArrayTransport: vastleggen van berichten
- Mail-facade en MailFake
- MailFake: Mailerselectie en vastleggen van Mailables
- Officiële Laravel-tests: verifiëren van verzending met Mailer en ArrayTransport