Sendgrid-nodejs: 使用入站邮件解析器解析传入电子邮件的示例

创建于 2017-10-13  ·  35评论  ·  资料来源: sendgrid/sendgrid-nodejs

发行摘要

问题及其发生环境的摘要。 如果合适,请包含重现该错误所需的步骤。 请随意提供屏幕截图,截屏视频和代码示例。

我无法弄清楚如何使用@ sendgrid / inbound-mail-parser程序包解析入站电子邮件。 需要一些示例代码

重现步骤

在sendgrid中设置解析路由(在此处链接:
https://www.dropbox.com/s/cb6lwrmon9qwjzq/Screenshot%202017-10-12%2016.03.49.png?dl=0)
这是发送给ngrok中路线的示例电子邮件的内容:
https://gist.github.com/machinshin/e38cf7d20ec6319edcfda63ff7aca594

我已经将parseroute连接到我的webhook,如下所示:

router.post('/api/email/parseroute', (req, res, next) => {
// have also tried:
router.post('/api/email/parseroute', bodyParser.raw(), (req, res, next) => {

    console.log(`-------------`)
    console.log(req.body)
    console.log(`-------------`)
    console.log(req.rawBody)
    console.log(`-------------`)

}

{}

未定义

如您所见,req.body为空,而req.rawBody为“未定义”
因此,我不清楚如何访问原始电子邮件数据,也不清楚如何处理该数据以及如何实例化入站邮件解析器。

您要共享的与报告的问题有关的任何其他信息。 特别是,为什么您认为这是一个错误? 您期望发生什么呢?

技术细节:

  • sendgrid-nodejs版本:6.1.4(最新提交:4c6d1cc)
  • Node.js版本:4.1.2
    “ @ sendgrid / inbound-mail-parser”:“ ^ 6.1.4”,
    “ @ sendgrid / mail”:“ ^ 6.1.4”,
easy help wanted docs update

最有用的评论

@ZeroCho

我们确实有一个包裹在这里,但遗憾的是没有很好的使用文档。 为此,您可能想签出Python Inbound Parser

最诚挚的问候,

埃尔默

因此,您应该然后编写文档。

所有35条评论

你好@machinshin

感谢您抽出宝贵时间报告此问题。 我已将此添加到我们的积压待进一步调查。

例子有更新吗? 我确实需要使用此解析器,但是我不知道该怎么做。

@ZeroCho

我们确实有一个包裹在这里,但遗憾的是没有很好的使用文档。 为此,您可能想签出Python Inbound Parser

最诚挚的问候,

埃尔默

SendGrid将其JSON入站解析数据作为表单/多部分数据发送。 由于body-parser不会处理该格式,因此req.body不会立即访问它。 我会用multer作为替代。

@ shishido92您能否扩展一个很好的示例。 似乎没有使用nodejs解析任何入站电子邮件的文档。 谢谢!

@stephenfjohnson @machinshin如果您使用expressjs,这可能会有所帮助

app.use(express.json({limit: '10mb'}));
app.use(express.urlencoded({
  extended: true,
  type: "multipart/form-data",
  limit: '10mb'
}));
app.post('/endpoint',  function (req, res, next) {
  // req.body contains the text fields
  console.log(req.body);
  console.log('body' + req.body);
  res.status(200).json('ok');
})

这样做将在请求正文中为您提供请求的内容。
但是,这会忽略附件。

@nathfreder我们在问题摘要中使用竖起大拇指的反应作为优先级的一部分。 请在顶部加👍。

@ childish-sambino, @ satyajeetjadhav👍

迟到比从来没有迟到;)
感谢您的更新,关闭此问题

我知道这个问题已经解决,但是我已经发现了这个问题,并且表示对入站邮件解析器的工作表示满意。 我需要做的主要事情是使用multer库处理multipart / form-data输入,然后使用@ sendgrid / inbound-mail-parser库的keyValues()方法,如下所示

在multer和Sendgrid中要求:

const multer = require('multer');
const upload = multer();
const mailParse = require('@ sendgrid / inbound-mail-parser');

在我的路由器声明中的POST方法中,使用upload.none()方法,因为我只是在获取文本(无附件):

router.post('/ mail',upload.none(),function(req,res,next)

然后,在该POST定义中,我使用keyValues()方法获取电子邮件的相关部分:

尝试{
const config = {keys:['to','from','subject','text',]};
const parsing = new mailParse(config,req.body);
让响应= parsing.keyValues();
让到= response.to;
让来自= response.from;
让subject = response.subject;
让messageBody = response.text
console.log('这是邮件的主题:',subject);
}

希望这是有用的。

大家好,有人可以分享一个如何解析附件的示例吗? 我使用的是相同的配置,但是附件来自无法读取的字符串


const app = express();
app.use(cors);
app.use(busboy());
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies.
app.use(bodyParser.json({limit: '5mb'}));

router.post('', upload.any(),function(req, res) {
  // console.log(req.body);
  // console.log(req.files);
  // res.send(req.body);

  const config = {keys: ['to', 'from', 'subject', 'text','attachments']};
  const parsing = new mailParse(config, req.body);
  let response = parsing.keyValues();
  let to = response.to;
  let from = response.from;
  let subject = response.subject;
  let messageBody = response.text
  console.log('This is the subject from the mail: ', response);
  res.send(200);
});

@ jhorsfield-tw发布的代码非常有帮助,因为@sendgrid/inbound-mail-parser没有文档,但是对我来说并不起作用。 mailParse的构造函数将request作为参数而不是请求正文。

const parsing = new mailParse(config, req);

@ZeroCho

我们确实有一个包裹在这里,但遗憾的是没有很好的使用文档。 为此,您可能想签出Python Inbound Parser

最诚挚的问候,

埃尔默

因此,您应该然后编写文档。

怎么还没有记载

仍然无法通过nodejs express解决...

重新打开,因为在文档中仍然没有此示例。

欢迎添加此功能的请求请求,并将根据优先级进行审查,但是Twilio SendGrid并未积极为该库构建新功能。

试图接收附件,但仍然没有运气...

试图接收附件,但仍然没有运气...

使用RAW

const config = {
          keys: ['to', 'from', 'subject', 'text', 'attachments']
        };
        const parsedMail = new parse(config, req); // req is https.Request type

        parsedMail.getRawEmail((rawMail: any) => {
           console.log(rawMail); // returns null or {}
       }

         parsedMail.attachments((attachmentData: Attachment[]) => {
              console.log('attachments1:'); // returns [ ]
              console.log(attachmentData);
              console.log(JSON.stringify(attachmentData));
            });

我正在尝试但没有运气...它返回一个空对象,当我做.attachments()我也得到一个空数组。

我正在使用Firebase云功能,使用入站邮件解析器没有任何成功,并且我希望有一些文档可以帮助我使用该库...

但是使用busboy(并在Sendgrid设置中取消选择“原始”)运行良好,除了一个导致我尝试使用mailparser的问题...

Sendgrid会在“字符集”字段中列出不同的编码,如下所示:
来自Gmail的电子邮件:
{“至”:“ UTF-8”,“ html”:“ UTF-8”,“主题”:“ UTF-8”,“来自”:“ UTF-8”,“文本”:“ UTF-8” }
来自Outlook的电子邮件:
{“ to”:“ UTF-8”,“ html”:“ iso-8859-1”,“ subject”:“ UTF-8”,“ from”:“ UTF-8”,“ text”:“ iso- 8859-1“}

当电子邮件包含国际字符(例如ÆØÅ)时,结果是text和html字段包含问号而不是实际的北欧字符。

如果我将busboy上的defCharset更改为Windows-1252,则文本和html值将正确显示,但其他字段将显示错误。

邮件解析器还会出现问题吗?还是邮件解析器会处理字段上的不同编码?

我对有兴趣的人使用busboy进行解析的代码:
(如果有人能告诉我我如何使用busboy解决上述问题,我将不胜感激。)

Exports.sendgridparse =函数。https.onRequest((req,res)=> {
const path = require('path');
const os = require('os');
const fs = require('fs');
const Busboy = require('busboy');

if (req.method !== 'POST') {
    // Return a "method not allowed" error
    return res.status(405).end();
}
const busboy = new Busboy({ headers: req.headers });    
const fields = {};
busboy.on('field', function(fieldname, value, fieldnameTruncated, valTruncated, encoding, mimetype){
    console.log('Busboy fild [' + fieldname + ']: value: ' + val);
fields[fieldname] = value;
});

让imageToBeUploaded = {};
让imagestoupuped = [];
让imageFileName;

busboy.on('file',(fieldname,file,filename,encoding,mimetype)=> {
console.log(字段名,文件,文件名,编码,mimetype);

file.on('data',function(data){
console.log('文件['+字段名+']得到了'+ data.length +'字节');
});
file.on('end',function(){
console.log('文件['+字段名+']已完成');
});

const imageExtension = filename.split('。')[filename.split('。')。length-1];
imageFileName = ${Math.round(Math.random() * 1000000000000).toString()}.${imageExtension} ;
const filepath = path.join(os.tmpdir(),imageFileName);
const url = https://firebasestorage.googleapis.com/v0/b/${environment.firebase.storageBucket}/o/${imageFileName}?alt=media ;
imageToBeUploaded = {文件路径,mimetype,imageFileName,imageExtension,url};
imagestobeuploaded.push(imageToBeUploaded);
file.pipe(fs.createWriteStream(filepath));
});

busboy.on('finish',async()=> {
//所有字段都可用(imagestobeuploaded和字段)并且可以保存到数据库
res.send(200);
});
busboy.end(req.rawBody);
});

@hhetland那么,您能够使用

@matheustavaresdev-是的,我正在使用

首先,将它们保存到busboy.on('file')中的tmp文件夹中,然后使用变量“ imagestobeuploaded”中的信息,将其保存到busboy.on('finish')中的firebase中的存储桶中。

太好了,谢谢!!!!!!!!!!!!

2020年4月,仍然没有官方文档,对不对?

我知道这个问题已经解决,但是我已经发现了这个问题,并且表示对入站邮件解析器的工作表示满意。 我需要做的主要事情是使用multer库处理multipart / form-data输入,然后使用@ sendgrid / inbound-mail-parser库的keyValues()方法,如下所示

在multer和Sendgrid中要求:

const multer = require('multer');
const upload = multer();
const mailParse = require('@ sendgrid / inbound-mail-parser');

在我的路由器声明中的POST方法中,使用upload.none()方法,因为我只是在获取文本(无附件):

router.post('/ mail',upload.none(),function(req,res,next)

然后,在该POST定义中,我使用keyValues()方法获取电子邮件的相关部分:

尝试{
const config = {keys:['to','from','subject','text',]};
const parsing = new mailParse(config,req.body);
让响应= parsing.keyValues();
让到= response.to;
让来自= response.from;
让subject = response.subject;
让messageBody = response.text
console.log('这是邮件的主题:',subject);
}

希望这是有用的。

我发现,request.body位于表单数据中,并看到一个错误:
[嵌套] 24687-2020年5月1日,下午1:29:51 [ExceptionsHandler]减少没有初始值的空数组
TypeError:减少没有初始值的空数组
在Array.reduce(

代码:
keyValues(){
返回this.keys
.filter(key => this.payload [key])
.map(key =>({[key]:this.payload [key]}))
.reduce((keyValues,keyPayload)=> Object.assign(keyValues,keyPayload));
}

返回错误,因为this.payload不是结构化数据,而是多部分表单数据。

我无法使用nest-js进行此操作。 我在NestJS控制器中收到的webhook数据是多格式数据。 我不确定在这种情况下如何使用Multer。

external.post('/ mail',upload.none(),function(req,res,next)

我尝试这样做:

export class MultiformParser implements NestMiddleware { async use(req: Request, res: Response, next: Function) { console.log("before: ", req.body) var upload = multer(); await new Promise((resolve, reject) => { upload.none()(req, res, err => { if (err) { console.log(err) reject(err) } else { resolve() console.log("request: ", req.body) } }); }); console.log("after: ", req.body) next(); } }

但是,req.body返回:
request: [Object: null prototype] {}

之前会打印出多种格式的数据。

如果您使用的是无服务器(Google云功能或Firebase)

这可能会有所帮助: https :

使用服务生的方法: https ://stackoverflow.com/questions/51484307/how-to-parse-multipart-form-data-on-firebase-cloud-functions

使用Formidable在无服务器上解析多部分: https :

或这样: https :

这是我必须进行的更改,以便可以使用multer:

app.use(express.json())
app.use(express.urlencoded({extended:true}));
const upload = multer();
app.use(upload.none());

完成此操作后,便可以使用multer将webhook数据解析为
结构化键,值对。

2020年5月24日星期日,下午4:51 Danish Mohd [email protected]
写道:

如果您使用的是无服务器(Google云功能或Firebase)
这可能会有所帮助:
https://stackoverflow.com/questions/47242340/how-to-perform-an-http-file-upload-using-express-on-cloud-functions-for-firebase/48648805#48648805

使用Formidable在无服务器上解析多部分:
https://github.com/DanisHack/formidable-serverless


您收到此邮件是因为您发表了评论。
直接回复此电子邮件,在GitHub上查看
https://github.com/sendgrid/sendgrid-nodejs/issues/482#issuecomment-633312295
或退订
https://github.com/notifications/unsubscribe-auth/AB2ATHHFKBRZZDGGJ2D7SOLRTGQHNANCNFSM4D67CVZQ

-

Shweta Bhandare博士| 首席软件工程师

[email protected]

https://hicleo.com/
hicleo.com | Linkedin https://www.linkedin.com/company/hicleo/ | 推特
https://twitter.com/hi_cleo/ | Instagram的
https://www.instagram.com/hicleo.co/ | 脸书
https://www.facebook.com/hicleolabs

-

此消息可能包含机密,专有或受保护的信息。
如果您错误地收到此消息,请通过回复电子邮件通知发件人并删除此消息。

我们花了很多时间试图使它与Busboy一起在Google Cloud Functions中工作,无论我们遵循什么教程或指针,都无法实现。

因此,在有一定灵活性的情况下,我将把这个留给下一个人:使用Python Inbound Parser 。 他们提供的代码几乎是一份复制/粘贴工作,并且花费了不到一个小时的时间才能使其运行。

我知道这并不能解决这里的问题,但是我希望它可以节省其他人的麻烦。

我很高兴,我发现这张票......我快要疯了试图找到一些这方面的资料,并以某种方式是没有的

我真的很困惑。 我只是假设会有标准的文档-特别是因为它是开源的,但它由SendGrid(并且最终是Twilio,它具有出色的文档)支持。

对于这样简单的事情,您可能会想到至少会有一个例子。

尽管如此,对于遇到这个问题的任何人...

我建议改用MailParser

我很确定这是在后台使用的,但是至少MailParser拥有大量文档。 只需确保在入站解析设置中已检查POST the raw, full MIME message ,如下所示(_wow,一个example_)。

Example

通过阅读MailParser文档,我在几分钟内就完成了:

import { Request, Response } from "express";
import { simpleParser } from "mailparser";

export const inboundEmails = async (req: Request, res: Response) => {
  const parsedEmail = await simpleParser(req.body.email);

  console.log("subject", parsedEmail.subject);
  console.log("from", parsedEmail.from);
  console.log("to", parsedEmail.to);
  console.log("cc", parsedEmail.cc);
  console.log("bcc", parsedEmail.bcc);
  console.log("date", parsedEmail.date);
  console.log("messageId", parsedEmail.messageId);
  console.log("inReplyTo", parsedEmail.inReplyTo);
  console.log("replyTo", parsedEmail.replyTo);
  console.log("references", parsedEmail.references);
  console.log("html", parsedEmail.html);
  console.log("text", parsedEmail.text);
  console.log("textAsHtml", parsedEmail.textAsHtml);
  console.log("attachments", parsedEmail.attachments);

  res.sendStatus(200);
};

所有数据都是您想要的。

我还使用Multer中间件来分析SendGrid POST到我的端点的多部分/表单数据。

在您的中间件流中,它就像multer().any()一样简单。

干杯

我使用了原始的完整MIME消息,并使其与simpleParser一起使用,但是我切换回了已处理的版本,并使用了sengrid的inbound-mail-parser,因为simpleParser不能很好地将MIME转换为文本和html。

绝对需要一些文档。

@theweiweiway您是否介意发布一个示例,说明这两种方法在文本和html方面的区别? 我没有发现任何差异,我很好奇。

用于文字

Hi 123 Hi 123 Hi 123 www.hello.com

Hi 123 Hi 123 Hi 123 www. <http://www.hello.com/>hello <http://www.hello.com/>.com <http://www.hello.com/>

^不知道为什么会这样

对于html

<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Hi 123<div class=""><b class="">Hi 123</b></div><div class=""><b class=""><u class="">Hi 123</u></b></div><div class=""><b class=""><u class="">www.</u>hello</b>.com</div></body></html>

<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class="">Hi 123</span><div class="" style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);"><b class="">Hi 123</b></div><div class="" style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);"><b class=""><u class="">Hi 123</u></b></div><div class="" style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);"><b class=""><u class=""><a href="http://www.hello.com" class="">www.</a></u><a href="http://www.hello.com" class="">hello</a></b><a href="http://www.hello.com" class="">.com</a></div></body></html>

我认为这与simpleParser软件包有关

这是我使用repress / multer的repo express-sendgrid-inbound-parse 。 这是一个易于上手的应用程序。 我建议不要选中POST the raw, full MIME message因为您可以访问更多电子邮件数据。

console.log('dkim: ', body.dkim)
console.log('to: ', body.to)
console.log('cc: ', body.cc)
console.log('from: ', body.from)
console.log('subject: ', body.subject)
console.log('sender_ip: ', body.sender_ip)
console.log('spam_report: ', body.spam_report)
console.log('envelope: ', body.envelope)
console.log('charsets: ', body.charsets)
console.log('SPF: ', body.SPF)
console.log('spam_score: ', body.spam_score)

if (rawFullMimeMessageChecked) {
    console.log('email: ', body.email)
} else {
    console.log('headers: ', body.headers)
    console.log('html: ', body.html)
    console.log('text: ', body.text)
    console.log('attachments: ', body.attachments)
    console.log('attachment-info: ', body['attachment-info'])
    console.log('content-ids: ', body['content-ids'])
}

在firebase的云功能上尝试了这个。
绝对不要工作。
还有其他解决方案吗?

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

thinkingserious picture thinkingserious  ·  4评论

Loriot-n picture Loriot-n  ·  4评论

thidasapankaja picture thidasapankaja  ·  4评论

amlcodes picture amlcodes  ·  4评论

TobiahRex picture TobiahRex  ·  3评论