Använda och förlänga Drupal 8 Mail API Del 1

I denna två delserier ska vi utforska Mail API i Drupal 8. Därigenom kommer vi att täcka två huvudaspekter: hur man använder den programmatiskt för att skicka e-post och hur man utökar den för att använda en extern tjänst som Mandrill.

För att demonstrera detta kommer vi i första delen att skapa en anpassad e-postadress mall som används för att skicka e-post till den nuvarande användaren när han / hon sparar en ny artikelnod. Dessutom kommer vi att se hur andra kan ändra det mall för att tillåta HTML-återgivning av e-postkroppen istället för den vanliga vanliga texten.

I den andra delen kommer vi att titta på att utöka postsystemet och integrera ett externt API för e-postleverans. För detta kommer vi att använda Mandrill och dess PHP-bibliotek som ger en bra grund för att interagera med dess API.

Allt arbete vi går igenom finns i detta Git-förråd som en del av en anpassad Drupal 8-modul som vi börjar skriva här. Så gärna checka ut om du vill följa med. Låt oss börja.

Den första förutsättningen för denna modul är dess .info fil:

d8mail.info.yml:

namn: Drupal 8 Mailer beskrivning: 'Demonterar användningen av Mail API i Drupal 8.' kärna: 8.x typ: modul 

Med detta ur vägen kan vi redan aktivera modulen på vår webbplats om vi vill.

Hur skickar vi en e-postadress?

Det finns två huvudsakliga steg för att skicka ett mail programmatiskt med Drupal 8. Vi behöver först implementera hook_mail () för att definiera en eller flera e-postmeddelanden mallar. Det andra steget är att använda posthanteraren för att skicka e-post med hjälp av en av dessa mallar.

Även ringde en krok, hook_mail () är inte en typisk krok men mer av en vanlig funktion som i allmänhet bara kallas av samma modul som implementerar den. Med andra ord, när du skickar ett mail programmatiskt, måste du ange modulnamnet implementering hook_mail () och den mall id du vill använda och det definieras av denna krok. Men vi ser det på en minut. Först, hur implementerar vi det?

d8mail.module:

/ ** * Implementerar hook_mail (). * / funktion d8mail_mail ($ key, & $ message, $ params) $ options = array ('langcode' => $ meddelande ['langcode'],); switch ($ key) case 'node_insert': $ message ['from'] = \ Drupal :: config ('system.site') -> få ('mail'); $ message ['subject'] = t ('Node skapad: @title', array ('@ title' => $ params ['node_title']), $ options); $ meddelande ['body'] [] = SafeMarkup :: checkPlain ($ params ['message']); ha sönder;  

Detta är en mycket enkel implementering som definierar en mall identifierad som node_insert (de $ key). De andra två funktionsargumenten är:

  • $ message: Godkänd genom referens, och inom vilken vi lägger till så mycket panna på vår email som vi behöver 
  • $ params: En rad extra data som behöver gå i e-postmeddelandet och det skickas från posthanteraren när vi försöker skicka e-postmeddelandet

Som ni kan se bygger vi upp $ message array med värden vi vill att detta e-postmeddelande ska inkludera i alla samtal. Vi ställer in en standard från värde som hämtas från konfigurationssystemet och som representerar huvudadressens e-postadress. Vi ställde in en kokplatta email ämne som låter mottagaren veta att en ny nod skapades, följt av nodens namn (som skickas in via $ params array). Ämnet kan också översättas till det språk som skickas från den som ringer. 

Slutligen kör vi meddelandet kropp genom strängavfettaren eftersom texten kan innehålla HTML och det kan bli trunkerat om vi inte kodar HTML-elementen. Och eftersom vi använder SafeMarkup klass måste vi använda sig av det högst upp:

använd Drupal \ Component \ Utility \ SafeMarkup; 

Dessutom är meddelandekroppen en uppsättning som senare kommer att vara imploderade in i en sträng. Och uppenbarligen finns det många andra parametrar som vi kan ställa in, till exempel rubriker, men det är tillräckligt för det här exemplet.

Och det är allt för hook_mail () genomförande. Låt oss nu vända sig till koden som körs varje gång en ny nod skapas, hook_entity_insert ():

/ ** * Implementerar hook_entity_insert (). * / funktion d8mail_entity_insert (Drupal \ Core \ Entity \ EntityInterface $ entity) om ($ entity-> getEntityTypeId ()! == 'nod' || ($ entity-> getEntityTypeId () === 'nod' && $ enhet -> bunt ()! == 'artikel')) return;  $ mailManager = \ Drupal :: service ('plugin.manager.mail'); $ module = 'd8mail'; $ key = 'node_insert'; $ till = \ Drupal :: currentUser () -> getEmail (); $ params ['message'] = $ entity-> get ('body') -> värde; $ params ['node_title'] = $ entity-> label (); $ langcode = \ Drupal :: currentUser () -> getPreferredLangcode (); $ send = true; $ result = $ mailManager-> mail ($ modul, $ key, $ till, $ langcode, $ params, NULL, $ send); $ message ['result']! == true) $ message = t ('Det gick inte att skicka din e-postmeddelande till @email för att skapa nod @id.', array ('@ email' => $ till , '@id' => $ entity-> id ())); drupal_set_message ($ message, 'error'); \ Drupal :: logger (d8mail) -> fel ($ message); lämna tillbaka;  $ message = t ('Ett e-postmeddelande har skickats till @email för att skapa nod @id.', array ('@ email' => $ till, '@id' => $ entity-> id ())) ; drupal_set_message ($ message); \ Drupal :: logger (d8mail) -> meddelande ($ message);  

Denna krok blir utlösad efter varje nod spara, och allt vi behöver göra är att se till att vi riktar in rätt nod och inkluderar vår logik.

Efter att ha kontrollerat att nodenheten är av typen artikel, vi laddar Drupal-posthanterarens tjänst och börja ange några värden för e-postmeddelandet. Vi behöver följande information:

  • Modulnamnet som implementerar hook_mail () och definierar vårt mall (vad jag nämnde ovan)
  • de mall id (the $ key)
  • Mottagarens e-postadress (den som finns på det aktuella användarkontot)
  • språket ($ Langcode) som går in i $ params array och vilken kommer att användas för att översätta ämnesmeddelandet
  • nodtiteln som kommer att läggas till e-postämnet
  • E-postkroppen, som i vårt fall kommer att vara värdet av nodens kroppsfält
  • Det booleska värdet indikerar huruvida e-postmeddelandet faktiskt ska skickas

Vi skickar sedan alla dessa värden till post() Metod för posthanteraren. Den senare ansvarar för att bygga e-postmeddelandet (ringer till höger hook_mail () genomförandet är en aspekt av detta) och slutligen delegera den faktiska leveransen till det ansvariga plugin. Som standard kommer detta att vara PHPMail, som använder standardvärdet post() funktion som kommer med PHP.

Om posthanteraren lyckas med att skicka e-postmeddelandet (den faktiska leveransen beaktas inte, utan snarare en framgångsrik PHP-åtgärd), post() Metoden kommer att returnera en array som innehåller a resultat nyckeln med vad som helst e-postprogrammet returnerar. Om vi ​​letar efter det värdet kan vi lära oss om e-poståtgärden var framgångsrik och informera användaren om att vi har anmält dem om deras åtgärd. I annat fall skriver vi ut och loggar ett felmeddelande.

Och det handlar om det. Om du rensar cacheminnet och skapar en artikelnnod bör du ange ett e-postmeddelande i din inkorg. Om du inte får något och det inte finns några felskyltar på din skärm, se till att du kontrollerar serverns loggar och mailkö för att verifiera att e-postmeddelanden skickas ut.

Innan jag går vidare vill jag göra en snabb notering om denna krokimplementering. I det här exemplet placerade jag all logiken inuti den direkt. Dessutom använde jag en tidig avkastning på toppen, vilket väsentligen betyder att ingen annan logik kan läggas till, men den som är specifik för artikelnoden. I reella applikationer rekommenderar jag att postadresslogiken omdirigeras till en separat funktion eller klass och uppskjutas till det. Dessutom bör du inte använda tidiga avkastningar inom krokimplementationerna utan ringa i stället andra funktioner om villkoren är uppfyllda. 

Hur ändrar vi en e-postadress?

När allt detta är på plats, har vi ett annat verktyg till vårt förfogande som gör att vi kan ändra en sådan befintlig inställning: hook_mail_alter (). Den här kroken kallas från posthanteraren innan det ansvariga postprogrammet skickar e-postmeddelandet. Syftet är att låta andra moduler göra slutliga ändringar i ett existerande e-postmeddelande som skickas ut.

Även om detta också kan användas av andra moduler, illustrerar vi ett exempel implementering inom samma modul som vi har arbetat med. För detta ändamål kommer vi att ändra e-postmeddelandet genom att ändra ett av dess standardhuvud för att omvandla det från vanlig text till HTML. Och så kan vi göra det här:

/ ** * Implementerar hook_mail_alter (). * / funktion d8mail_mail_alter (& $ message) switch ($ message ['key']) fall 'node_insert': $ message ['headers'] ['Content-Type'] = 'text / html; charset = UTF-8; format = flödade; delsp = ja; ha sönder;  

Som du kan se är det en enkel ändring av Innehållstyp rubrik som omvandlar e-post till HTML. På så vis analyseras HTML-enheter med ren text som HTML via postklienter. Och med hjälp av switchväxeln ser vi till att det bara händer för e-postmeddelandet mall vi definierade tidigare.

En sak att notera här är att alterkroken kallas efter det relevanta hook_mail () genomförande. Så efter detta är den enda behandlingen som sker på e-posten gjort inom formatera() Metoden för mail-plugin (verkställd av dess gränssnitt).

Slutsats

Och det är ganska mycket allt det finns att skicka e-postprogrammatiskt med Drupal 8. Vi har sett de steg som krävs för att programmässigt konfigurera e-post mallar som blir hydratiserade av postansvarig närhelst vi vill ha det. Vi har också nämnt standardleveransprogrammet för e-post som används för att skicka e-postmeddelanden i Drupal 8. Och äntligen har vi sett hur andra moduler nu kan ändra vårt e-postmeddelande genom att lägga till nya rubriker, ändra ämnet, sammanlänkande värden till postkroppen , etc.

I nästa artikel kommer vi att titta på att ersätta standard PHPMail-plugin med vår egen anpassade implementering. Vi kommer att skapa en mailare som använder Mandrill med hjälp av sitt PHP-bibliotek. Målet är att låta vår egen modul använda denna mailare medan resten av programmet fortsätter att använda standard PHPMailer.