Skip to content
Snippets Groups Projects
Commit 46928120 authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Improved email generation using the library PHPMailer

parent 97c4886b
Branches
Tags
No related merge requests found
vendor
composer.lock
nbproject
logs
config.php
test
<?php
namespace RAP;
/**
* This class is used to build an e-mail message body both in HTML and in its
* equivalent plaintext.
*/
class MailBodyBuilder {
private $htmlBody;
private $textBody;
private $openedHTMLTags;
private $editable;
function __construct() {
$this->htmlBody = "";
$this->textBody = "";
$this->openedHTMLTags = [];
$this->editable = true;
}
private function checkEditable() {
if (!$this->editable) {
throw new \Exception("You cannot edit the body after it has been generated");
}
}
public function addText($text) {
$this->checkEditable();
$this->htmlBody .= $text;
$this->textBody .= $text;
return $this;
}
public function addLineBreak() {
$this->checkEditable();
$this->htmlBody .= "<br>\n";
$this->textBody .= "\n";
return $this;
}
public function addHr() {
$this->checkEditable();
$this->htmlBody .= "<hr/>\n";
$this->textBody .= "\n---------------------\n";
return $this;
}
public function addLinkWithDescription($url, $text) {
$this->checkEditable();
$this->htmlBody .= '<a href="' . $url . '" target="blank_">' . $text . "</a>\n";
$this->textBody .= $text . " ( " . $url . " ) ";
return $this;
}
public function addLink($url) {
$this->checkEditable();
$this->htmlBody .= '<a href="' . $url . '" target="blank_">' . $url . "</a>\n";
$this->textBody .= $url . " ";
return $this;
}
public function addEmailAddress($email, $description) {
$this->checkEditable();
$this->htmlBody .= '<a href="mailto:' . $email . '">' . $description . '</a>';
$this->textBody .= $description . " (" . $email . ")";
return $this;
}
private function openHTMLTag($tag, $equivalentPlainText) {
$this->checkEditable();
if (in_array($tag, $this->openedHTMLTags)) {
throw new \Exception("You are already inside a " . $tag . " tag!");
}
$this->openedHTMLTags[] = $tag;
$this->htmlBody .= "<" . $tag . ">";
$this->textBody .= $equivalentPlainText;
return $this;
}
private function closeHTMLTag($tag, $equivalentPlainText) {
$this->checkEditable();
if ($this->openedHTMLTags[count($this->openedHTMLTags) - 1] !== $tag) {
throw new \Exception("You are not inside a " . $tag . " tag!");
}
array_pop($this->openedHTMLTags);
$this->htmlBody .= "</" . $tag . ">";
$this->textBody .= $equivalentPlainText;
return $this;
}
public function startBold() {
return $this->openHTMLTag("strong", "*");
}
public function endBold() {
return $this->closeHTMLTag("strong", "*");
}
public function startParagraph() {
return $this->openHTMLTag("p", "");
}
public function endParagraph() {
return $this->closeHTMLTag("p", "\n");
}
public function startList() {
return $this->openHTMLTag("ul", "\n");
}
public function startListItem() {
return $this->openHTMLTag("li", " * ");
}
public function endListItem() {
return $this->closeHTMLTag("li", "\n");
}
public function endList() {
return $this->closeHTMLTag("ul", "\n");
}
private function checkEnd() {
if (count($this->openedHTMLTags) > 0) {
$unclosedTags = "";
foreach ($this->openedHTMLTags as $tag) {
$unclosedTags .= $tag . " ";
}
throw new \Exception("You must close all tags before generating email body! Unclosed tags: " . $unclosedTags);
}
}
private function setCompatibleLineBreaks($value) {
return str_replace("\n", "\n\r", $value);
}
private function finalizeBodyIfNecessary() {
if ($this->editable) {
$this->checkEnd();
$this->htmlBody = $this->setCompatibleLineBreaks($this->htmlBody);
$this->textBody = $this->setCompatibleLineBreaks($this->textBody);
$this->editable = false;
}
}
public function getTextPlainBody() {
$this->finalizeBodyIfNecessary();
return $this->textBody;
}
public function getHTMLBody() {
$this->finalizeBodyIfNecessary();
return $this->htmlBody;
}
}
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
namespace RAP; namespace RAP;
use \PHPMailer\PHPMailer\PHPMailer;
/** /**
* Manage mail sending. * Manage mail sending.
* Currently used only for join email messages. * Currently used only for join email messages.
...@@ -32,10 +34,20 @@ class MailSender { ...@@ -32,10 +34,20 @@ class MailSender {
private $serverName; private $serverName;
private $basePath; private $basePath;
private $mbb;
public function __construct($serverName, $basePath) { public function __construct($serverName, $basePath) {
$this->serverName = $serverName; $this->serverName = $serverName;
$this->basePath = $basePath; $this->basePath = $basePath;
$this->mbb = new MailBodyBuilder();
}
private function addDescriptionItem($key, $value) {
$this->mbb->startBold()
->addText($key)
->endBold()
->addText(": " . $value)
->addLineBreak();
} }
/** /**
...@@ -47,53 +59,86 @@ class MailSender { ...@@ -47,53 +59,86 @@ class MailSender {
*/ */
public function sendJoinEmail(User $recipientUser, User $applicantUser, $token) { public function sendJoinEmail(User $recipientUser, User $applicantUser, $token) {
$subject = "IA2 RAP: Join request"; global $auditLog;
$header = "From: noreply@" . $this->serverName . "\r\n";
$header .= "Content-Type: text/html; charset=UTF-8";
$confirmJoinURL = $this->basePath . '/confirm-join?token=' . $token; $confirmJoinURL = $this->basePath . '/confirm-join?token=' . $token;
$body = "Dear IA2 user,<br/><br/>"; $this->mbb->startParagraph()
$body .= "the following user requested to join your accounts on the " ->addText("Dear IA2 user,")
. "<a href=\"https://sso.ia2.inaf.it/rap-ia2/\" target=\"blank_\">RAP facility</a>:<br/><br/>"; ->addLineBreak()
->addText("the following user requested to join your accounts on the ")
->addLinkWithDescription("https://sso.ia2.inaf.it/rap-ia2/", "RAP facility")
->addText(":")
->endParagraph();
foreach ($applicantUser->identities as $identity) { foreach ($applicantUser->identities as $identity) {
$body .= "<b>Type</b>: " . $identity->type . "<br/>"; $this->addDescriptionItem("Type", $identity->type);
if ($identity->name !== null) { if ($identity->name !== null) {
$body .= "<b>Name</b>: " . $identity->name . "<br/>"; $this->addDescriptionItem("Name", $identity->name);
} }
if ($identity->surname !== null) { if ($identity->surname !== null) {
$body .= "<b>Surname</b>: " . $identity->surname . "<br/>"; $this->addDescriptionItem("Surname", $identity->surname);
} }
$this->addDescriptionItem("E-mail", $identity->email);
$body .= "<b>E-mail</b>: " . $identity->email . "<br/>";
if ($identity->eppn !== null) { if ($identity->eppn !== null) {
$body .= "<b>Eppn</b>: " . $identity->eppn . "<br/>"; $this->addDescriptionItem("Eppn", $identity->eppn);
} }
if ($identity->institution !== null) { if ($identity->institution !== null) {
$body .= "<b>Institution</b>: " . $identity->institution . "<br/>"; $this->addDescriptionItem("Institution", $identity->institution);
} }
$body .= "<br/>"; $this->mbb->addLineBreak();
} }
$body .= "<br/>If you and this user are <b>the same person</b> click on the following link for joining your accounts:<br/>"; $this->mbb->startParagraph()
$body .= "<a href=\"$confirmJoinURL\" target=\"blank_\">$confirmJoinURL</a>"; ->addText("If you and this user are ")
$body .= "<br/><br/>Otherwise you can ignore this email.<br/>"; ->startBold()
->addText("the same person")
$body .= '<p><b>Please don\'t use this functionality for sharing resources between your coworkers</b>, use <a href="https://sso.ia2.inaf.it/grouper">Grouper</a> for that.</p>'; ->endBold()
$body .= '<br/>'; ->addText(" click on the following link for joining your accounts: ")
->addLink($confirmJoinURL)
$body .= "<b>*** This is an automatically generated email, please do not reply to this message ***</b><br/>"; ->addLineBreak()
$body .= "If you need information please contact <a href=\"mailto:ia2@oats.inaf.it\">IA2 Staff</a>"; ->addText("Otherwise you can ignore this email.")
->endParagraph()
mail($recipientUser->getPrimaryEmail(), $subject, $body, $header); //
->startParagraph()
->startBold()
->addText("Please don't use this functionality for sharing resources between your coworkers")
->endBold()
->addText(", use ")
->addLinkWithDescription("https://sso.ia2.inaf.it/grouper", "Grouper")
->addText(" for that.")
->endParagraph()
//
->addLineBreak()
->startBold()
->addText("*** This is an automatically generated email, please do not reply to this message ***")
->endBold()
->addLineBreak()
->addText("If you need information please contact ")
->addEmailAddress("ia2@oats.inaf.it", "IA2 Staff");
$mail = new PHPMailer(true); // Passing `true` enables exceptions
try {
$toAddress = $recipientUser->getPrimaryEmail();
$mail->isSMTP();
$mail->Port = 25;
$mail->setFrom("noreply@" . $this->serverName, 'IA2 SSO');
$mail->addAddress($toAddress);
$mail->CharSet = 'utf-8';
$mail->Subject = "IA2 RAP: Join request";
$mail->Body = $this->mbb->getHTMLBody();
$mail->AltBody = $this->mbb->getTextPlainBody();
$auditLog->info("JOIN email. Sending to " . $toAddress);
$mail->send();
} catch (\Exception $ex) {
error_log($ex->getMessage());
throw $ex;
}
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment