繁体   English   中英

使用Sendgrid / Nodemailer将Angular表单数据发布到Node.js

[英]Post Angular form data to Node.js with Sendgrid/Nodemailer

我已按照此示例将我的Angular应用程序中的数据发布到Node.js,以将webform发布到Sendgrid。 这在一些变化后工作正常,并且非常感谢快速入门。 将表单数据发布到Sendgrid现在正在运行!

对于这个项目我正在使用Angular Fullstack来在我的Angular应用程序中使用Node功能。

但是,此示例只包含输入字段和textarea。 我希望能够添加文件(PDF,Docx等),以便人们可以通过Sendgrid向收件人发送附件。 我搜索了一个解决方案,但找不到一个有效的例子。 也许是因为我不想实现的目标。

我的观点(客户):

<div ng-controller="ContactFormCtrl" id="contactformbox" style="margin-top:50px;" class="mainbox" >                    
  <div class="panel panel-info" >

          <div class="panel-heading">
              <div class="panel-title">Solliciteer direct</div>
          </div>     

          <div style="padding-top:30px" class="panel-body" >
              <form id="loginform" class="form-horizontal" role="form" name="contactform">

                  <div style="margin-bottom: 25px" class="input-group">
                    <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
                    <input type="email" name="to" ng-model="email.to" ng-required="true" id="email-to" class="form-control" name="username" value="" placeholder="The emailadres from the employer">       
                  </div>

                  <div style="margin-bottom: 25px" class="input-group">
                      <span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
                      <input type="email" name="from" ng-model="email.from" ng-required="true" id="email-from" class="form-control" name="email-from" placeholder="Your e-mail address">
                  </div>

                  <div style="margin-bottom: 25px" class="input-group">
                      <span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
                      <input type="text" name="subject" ng-model="email.subject" ng-required="true" id="email-subject" class="form-control" name="subject" placeholder="Your subject please">
                  </div>

                  <div style="margin-bottom: 25px" class="input-group">
                      <input type="file" name="file" ng-model="email.file" ng-required="true" id="email-file" class="form-control" name="file">
                  </div>

                  <div style="margin-bottom: 25px" class="input-group">
                    <textarea ng-model="email.text" name="text" placeholder="Enter Text Here.." class="form-control" rows="5" id="comment"></textarea>
                  </div>    

                  <div style="margin-top:10px" class="form-group">
                      <!-- Button -->
                      <div class="col-sm-12 controls">
                            <button id="emailSubmitBn" class="btn btn-success" type="submit" ng-click="submitEmail()">Submit</button>
                      </div>
                  </div>
              </form>     
        </div>                     
  </div>  

我的控制器(客户):

angular.module('angularMyApp')
.controller('ContactFormCtrl', function ($scope, $http) {
  $scope.submitEmail = function() {

    console.log("TEST");
    //Request
    $http.post('/api/email', $scope.email) 
    .success(function(data, status) {
        console.log("Sent ok");
    })
    .error(function(data, status) {
        console.log("Error");
    })
  };
});

我的APP.JS(服务器):

'use strict';

// Set default node environment to development
process.env.NODE_ENV = process.env.NODE_ENV || 'development';

var express = require('express');
var config = require('./config/environment');
var http = require('http');
var bodyParser = require('body-parser');

var options = {
    auth: {
        api_key: process.env.SENDGRID_APIKEY; 
    }
}

var nodemailer = require('nodemailer');
var sgTransport = require('nodemailer-sendgrid-transport');

// Setup server
var app = express();
var server = require('http').createServer(app);
require('./config/express')(app);
require('./routes')(app);

var mailer = nodemailer.createTransport(sgTransport(options));

app.post('/api/email', function(req, res) {
var mailOptions = {
    to: ['test@test.nl', req.body.to],
    from: req.body.from,
    subject: req.body.subject,
    text: req.body.text
};

mailer.sendMail(mailOptions, function(err, res) {
    if (err) { 
        console.log(err) 
    }
    console.log(res);
  });
});

// Start server
server.listen(config.port, config.ip, function () {
console.log('Express server listening on %d, in %s mode', config.port, app.get('env'));
});

// Expose app
exports = module.exports = app;

那么有两个主要问题:

  1. Clientside:如何在此表单中将附件从Angular发布到Node? 我是否必须先上传文件,还是可以使用$ http.post将其发送到Node? 或者我必须使用ng-file-upload?
  2. Serverside:我如何向Sendgrid / Nodemailer发送附件。 从服务器上的app.js向Sendgrid发送硬编码文件不起作用。 邮件成功发送到Sendgrid但它不包含附件。

提前谢谢了!

1.使用角度的表单上载文件

您遇到的第一个问题是ng-model不能与<input type="file" /> 因此,您需要创建一个自定义指令来使用该文件填充模型。

.directive('fileModel', ['$parse', function ($parse) {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            var model = $parse(attrs.fileModel);
            var modelSetter = model.assign;

            element.bind('change', function(){
                scope.$apply(function(){
                    modelSetter(scope, element[0].files[0]);
                });
            });
        }
    };
}]);

然后在文件输入元素上使用指令,如下所示:

<input type="file" file-model="email.attachment" ng-required="true" id="email-attachment" name="attachment" class="form-control" />

请注意,我将email.file更改为email.attachment以避免混淆其余代码。

接下来,您需要在AJAX请求中包含该文件。 您需要使用FormData 使用FormData.append()从作用域填充它:

$scope.submitEmail = function() {
    var formData = new FormData();
    Object.keys($scope.email).forEach(function(key) {
        formData.append(key, $scope.email[key]);
    });
    $http.post('/api/email', formData, {
        transformRequest: angular.identity,
        headers: {'Content-Type': undefined}
    }).then(function(data, status) {
        console.log("Sent ok");
    }, function(data, status) {
        console.log("Error");
    });
};

注意我还将配置对象传递给$http.post() 这是为了防止角度解析FormData对象并设置内容类型。

对于这部分答案,我非常依赖这篇博客文章

2.使用Nodemailer发送附件

要访问express中的文件,请使用multer

安装:

$ npm install --save multer

用法:

var multer = require('multer');
var upload = multer();

app.post('/api/email', upload.single('attachment'), function(req, res) {
    // req.file contains the 'attachment' file
    ...
});

电子邮件字段的Nodemailer自述文件部分,它说要使用attachments属性,这是一个attachment对象数组。

app.post('/api/email', upload.single('attachment'), function(req, res) {
    var mailOptions = {
        to: ['test@test.nl', req.body.to],
        from: req.body.from,
        subject: req.body.subject,
        text: req.body.text,
        attachments: [
            {
                filename: req.file.originalname,
                content: req.file.buffer
            }
        ]
    };

    mailer.sendMail(mailOptions, function(err, res) {
        if (err) { 
            console.log(err) 
        }
        console.log(res);
    });
});

上面的示例将附件保留在内存中,如果频繁上载大文件,这可能会很糟糕。 您可以将文件写入磁盘:

var upload = multer({ dest: '/uploads' });

然后,不是将文件的buffer设置为附件的content ,而是将附件的path设置为文件的path

attachments: [
    {
        filename: req.file.originalname,
        path: req.file.path
    }
]

感谢gilly3,我终于完成了工作。 我不得不对他的代码做一个小改动。 在控制器中我改变了:

formData.set(key, $scope.email[key]);

到以下代码:

formData.append(key, $scope.email[key]);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM