Sam Aghdam
Sam Aghdam

Reputation: 21

creating dynamic html emails with angularJS and mail with php

I have been trying to solve this and have been looking everywhere. Apologies in advance if this sounds stupid or there is a duplicate question somewhere that I have missed.

I am trying to create dynamic email content and send the email via php mail. I want to use angularJS to compile the html content and using $http.post method send to a submit.php to send email.

I can manually enter in the html content in php and no problem but having a compiled dynamic html is the issue.

I am really not too sure how to tackle this, so any help would be much appreciated.

Thanks,

My angular controller:

    $scope.url = 'submit.php';

    $scope.formsubmit = function(isValid) {


        if (isValid) {


            $http.post($scope.url, {"name": $scope.name, "email": $scope.email, "message": $scope.message }).
                    success(function(data, status) {
                        console.log(data);
                        $scope.status = status;
                        $scope.data = data;
                            $scope.result = data; 
})
}
}

submit.php

    $post_date = file_get_contents("php://input");
$data = json_decode($post_date);
$to = $data->email;
$from = "[email protected]";
$name = $data->name;
$subject = "Email from AngularJS";

$htmlContent = $data->message;

I have added my code below :

index.html:

    <!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <title>Dynamic Email AngularJS</title>

</head>

<body ng-app="myApp" ng-cloak>

    <div ng-controller="formCtrl">


    <pre ng-model="result">
                {{result}}
    </pre>
    <form name="userForm">
    <input type="text" class="form-control" ng-model="$parent.name" placeholder="Name Lastname" required>
    <input type="text" class="form-control" ng-model="$parent.email" placeholder="[email protected]" required>


    <div ng-view></div>
    <button ng-click="add()">New Item</button>
    <button type="submit" class="btn" ng-click="formsubmit(userForm.$valid)"  ng-disabled="userForm.$invalid">Submit </button>
    </form>
    </div>

    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>

    <script src="//code.angularjs.org/1.4.3/angular-route.min.js"></script>
    <script src="app.js"></script>


</body>

</html>

app.js:

myApp.controller("formCtrl", ['$scope', '$http','$templateRequest','$compile', function($scope, $http, $templateRequest, $compile) {

$scope.lists = [
{
"year":"year I",
"semesters":[
                {

                "label": "Semester I",
                "max": "4",
                "courses": [
                    {"name": "Introductory Accounting I", "type": "populated"},
                    {"name": "Principles of Economics I", "type": "populated"},
                ]
                },

                {
                "label": "Semester II",
                "max": "4",
                "courses": [
                    {"name": "Accounting Method II", "type": "populated"},

                ]
                }
        ]
},

{
"year":"year II",
"semesters":[
                {
                "label": "Semester I",
                "max": "4",
                "courses": [
                    {"name": "Introductory Accounting I", "type": "levelII"},
                    {"name": "Business Finance I", "type": "levelII"}
                ]
                },

                {
                "label": "Semester II",
                "max": "4",
                "courses": [
                    {"name": "Accounting Method II", "type": "levelII"},
                    {"name": "Management Accounting II", "type": "levelII"},

                ]
                }
        ]
}
]

$scope.add = function () {
  $scope.lists.push(
      {
"year":"year III",
"semesters":[
                {
                "label": "Semester I",
                "max": "4",
                "courses": [
                    {"name": "Introductory Accounting I", "type": "levelII"},
                    {"name": "Business Finance I", "type": "levelII"}
                ]
                },

                {
                "label": "Semester II",
                "max": "4",
                "courses": [
                    {"name": "Accounting Method II", "type": "levelII"},
                    {"name": "Management Accounting II", "type": "levelII"},

                ]
                }
        ]
});
}

$scope.url = 'submit.php';

$scope.formsubmit = function(isValid) {

    if (isValid) {

        $templateRequest('email.html').then(function(html) {

        $scope.contentHtml = $compile(html);
        });
        $http.post($scope.url, {"name": $scope.name, "email": $scope.email, "message": $scope.contentHtml }).
                success(function(data, status) {
                    console.log(data);
                    $scope.status = status;
                    $scope.data = data;
                    $scope.result = data; 
                })
    }else{

          alert('Form is not valid');
    }
}

}]);

submit.php:

    <?php


$post_date = file_get_contents("php://input");
$data = json_decode($post_date);
$to = $data->email;
$from = "[email protected]";
$name = $data->name;
$subject = "Dynamic Email";


$htmlContent = $data->message;

// Set content-type header for sending HTML email
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";

// Additional headers
$headers .= 'From: '.$from . "\r\n";


if(mail($to,$subject,$htmlContent,$headers)) {

    echo "Mail Sent. Thank you " . $name . ", we will contact you shortly.";    

} else {


    echo 'Sorry there was an error sending your message. Please try again later.';

}


echo "Name : ".$data->name."\n";
echo "Email : ".$data->email."\n";
echo "Hero : ".$data->hero."\n";
echo "Message": $htmlContent;



?>

email.html

<table ng-repeat="list in lists">
    <tr>
        <td>
            <h1>{{list.year}}</h1>
        </td>
    </tr>
    <tr>
        <td ng-repeat="semester in list.semesters">
            <table>
                <tr>
                    <td>
                        <h3>{{semester.label}}</h3>


                         <ul>
                             <li ng-repeat="course in semester.courses">{{course.name}}</li>
                         </ul>

                    </td>
                </tr>
            </table>
        </td>

    </tr>
</table>

Upvotes: 1

Views: 2003

Answers (2)

Yogesh Mahale
Yogesh Mahale

Reputation: 71

I have successfully implemented this architecture in my one project. I have created separate service to get email template. I passed URL and $scope object to getTemplate() method and this method will return compiled email template to me.

templateService.js

angular.module('myApp').factory("TemplateService", ['$resource', '$q', '$rootScope', '$templateRequest', '$compile', '$timeout', function ($resource, $q, $rootScope, $templateRequest, $compile, $timeout) {
    class TemplateService {
        constructor() {

        }

        /**
         * Get the template from url and then compile it with data.
         * @param url
         * @param $scope
         * @returns {*|Promise<T>}
         */
        static getTemplate(url, $scope) {
            return $templateRequest(url)
                .then(function(response){
                    let template = angular.element('<div></div>');
                    template.html(response);

                    //3. Pass the data to email template, in data will be merged in it
                    $compile(template)($scope);

                    return $timeout(function(){
                        return template.html();
                    }, 300);
                })
                .catch(function(err){
                    return $templateRequest('views/templates/404.html');
                });
        }
    }

    return TemplateService;
}]);

contact_email.html

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="https://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Email</title>
    </head>
<body leftmargin="0" marginwidth="0" topmargin="0" marginheight="0" offset="0">
<table align="center" border="0" cellpadding="0" cellspacing="0" height="100%" width="100%" id="bodyTable" style="background: #f2f2f2;padding:40px 10px;">
    <tr>
        <td align="center" valign="top" id="bodyCell">
            <table border="0" cellpadding="0" cellspacing="0" id="templateContainer" style="background: white;text-align: center;border: 1px solid grey;padding: 20px;box-shadow: 0 0 5px 2px grey;margin:0 auto;">
            <tr>
                <td align="center" valign="top">
                    <table border="0" cellpadding="0" cellspacing="0" width="100%" id="templateBody">
                        <tr>
                            <td valign="top" class="bodyContent">
                                Hello  {{ contactEmailCtrl.contact.firstName }} 
                                <p compile="contactEmailCtrl.message">
                                </p>
                                <p>
                               
                                </p>
                            </td>
                        </tr>
                    </table>
                </td>
                </tr>
            </table>
        </td>
    </tr>
</table>
</body>
</html>

Usage in controller contact.controller.js

angular.module('myApp').controller('ContactController', ['$scope', 'Global', 'TemplateService', $scope, Global, TemplateService]) {
let vm = this;
vm.sendEmail = function(params) {
        
        //1. Prepare email template, Pass data to email template and compile it
        $scope.contactEmailCtrl = {
            user: Global.user,
            message: $scope.emailCommunication.message || null,
        };

        TemplateService.getTemplate('views/templates/emails/contact_email.html', $scope).then(function(emailBody) {               
            console.log('--> | emailBody ', emailBody);
            //Todo: Send email
            let emailParams = {
              tos: '[email protected]',
              subject: 'subject goes here',
              emailBody: emailBody
            }
            // EmailService.sentEmail(emailParams); // Either send by PHP or Nodejs Or Ruby whatever
         

        }).catch(function(err) {
            console.log(' err ', err);
        });
    };
    
    }

This is whole implementation. Hope this will help who wants to maintain clean architecture and separate email html and inject on the fly to send email.

Upvotes: 0

Dirk Simons
Dirk Simons

Reputation: 33

I had to do the very same thing. But my setup is somewhat different. My Backend is a Firebase.com database. Loaded into my frontend via angularFire, the library for loading stuff into an angular project. I have a mail template in the front-end. In fact, i plan to let users choose their e-mail template from several provided ones. I just fill in the fields, a but like a mail-merge in MS-Office. On the serverside, i'm using php-mailer (google it!) In big lines, this is what's happening: - Create vars like mailTo (all the emails where i have to send mail to) and bind them to the $scope (yeah i know i shouldn't do that but stay with me) - other stuf from the database records that should be in the mail, i bind to the $scope again. - and then i do this:

$templateRequest("templates/mail-packs/mail-1.html")
       .then(function(emailtemplate) {
             var base = angular.element('<div></div>');
             base.html(emailtemplate);
             $compile(base)($scope);
             $timeout(function(){
                  mail = base.html()
                  console.log(mail);
                  constructMail(mail)
             }, 300)
        })

the base variabel was needed beceause you are not compling to the DOM. You have to trick angular there and start with a blank DOM. The function constructMail() is a function just doing that, prepping the data to send to the php-mailer.

Upvotes: 1

Related Questions