1

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>
0

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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.

1 Comment

I have take reference from this link

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.