Sendgrid-nodejs: Ejemplo sobre el uso de inbound-mail-parser para analizar correos electrónicos entrantes

Creado en 13 oct. 2017  ·  35Comentarios  ·  Fuente: sendgrid/sendgrid-nodejs

Resumen de asuntos

Un resumen del problema y el entorno en el que ocurre. Si es adecuado, incluya los pasos necesarios para reproducir el error. No dude en incluir capturas de pantalla, screencasts, ejemplos de código.

No puedo averiguar cómo usar el paquete @ sendgrid / inbound-mail-parser para analizar los correos electrónicos entrantes. necesito un código de ejemplo

Pasos para reproducir

Configure una ruta de análisis en sendgrid (vinculado aquí:
https://www.dropbox.com/s/cb6lwrmon9qwjzq/Screenshot%202017-10-12%2016.03.49.png?dl=0)
este es el contenido de un correo electrónico de ejemplo a la ruta en ngrok:
https://gist.github.com/machinshin/e38cf7d20ec6319edcfda63ff7aca594

He conectado el parseroute a mi webhook así:

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(`-------------`)

}

{}

indefinido

Como puede ver, req.body está vacío y req.rawBody es 'undefined'
Por lo tanto, no tengo claro cómo obtener acceso a los datos sin procesar del correo electrónico, ni qué hacer con esos datos después y cómo crear una instancia del analizador de correo entrante.

Cualquier otra información que desee compartir que sea relevante para el problema que se informa. Especialmente, ¿por qué considera que esto es un error? ¿Qué esperas que suceda en su lugar?

Detalles técnicos:

  • sendgrid-nodejs Versión: 6.1.4 (última confirmación: 4c6d1cc)
  • Versión de Node.js: 4.1.2
    "@ sendgrid / inbound-mail-parser": "^ 6.1.4",
    "@ sendgrid / mail": "^ 6.1.4",
easy help wanted docs update

Comentario más útil

Hola @ZeroCho ,

Tenemos un paquete aquí , pero desafortunadamente no hay una buena documentación de uso. Para eso, es posible que desee consultar el analizador de entrada de Python .

Con los mejores deseos,

Elmer

Entonces deberías escribir documentación.

Todos 35 comentarios

Hola @machinshin ,

Gracias por tomarse el tiempo para informar esto. He agregado esto a nuestro trabajo pendiente para una mayor investigación.

¿Alguna actualización sobre el ejemplo? Realmente necesito usar este analizador pero no sé cómo hacerlo.

Hola @ZeroCho ,

Tenemos un paquete aquí , pero desafortunadamente no hay una buena documentación de uso. Para eso, es posible que desee consultar el analizador de entrada de Python .

Con los mejores deseos,

Elmer

SendGrid envía sus datos de análisis entrante JSON como datos de formulario / de varias partes. Req.body no accederá inmediatamente a esto, ya que el analizador corporal no se ocupa de ese formato. Usaría multer como alternativa.

@ shishido92 ¿Podría ampliar un buen ejemplo de cómo hacerlo? Parece que la documentación para analizar los correos electrónicos entrantes con nodejs es simplemente inexistente. ¡Gracias!

@stephenfjohnson @machinshin Si está utilizando expressjs, esto podría ayudar

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');
})

Hacer esto le dará el contenido de la solicitud en el cuerpo de la solicitud.
Sin embargo, esto ignora los archivos adjuntos.

@nathfreder Usamos

@ childish-sambino, @satyajeetjadhav 👍

Más tarde más tarde que nunca;)
Gracias por la actualización, cerrando este problema

Sé que esto se ha cerrado, pero acabo de detectar este problema y tengo Express con inbound-mail-parser funcionando. Lo principal que tenía que hacer era usar la biblioteca multer para manejar la entrada multipart / form-data y luego usar el método keyValues ​​() de la biblioteca @ sendgrid / inbound-mail-parser como se muestra a continuación

require en multer y Sendgrid:

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

en la declaración de mi enrutador para el método POST, use el método upload.none () ya que solo estaba recibiendo texto (sin archivos adjuntos):

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

Dentro de esa definición POST, luego uso el método keyValues ​​() para obtener las partes relevantes del correo electrónico:

tratar {
const config = {claves: ['a', 'desde', 'asunto', 'texto',]};
análisis constante = new mailParse (config, req.body);
dejar respuesta = parsing.keyValues ​​();
let to = response.to;
dejar de = respuesta. de;
let subject = response.subject;
dejar messageBody = response.text
console.log ('Este es el asunto del correo:', asunto);
}

Espero que sea de alguna utilidad.

Hola a todos, ¿alguien puede compartir un ejemplo de cómo analizar archivos adjuntos? Estoy usando las mismas configuraciones, pero el archivo adjunto viene en una cadena ilegible


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);
});

El código publicado por @ jhorsfield-tw fue muy útil ya que @sendgrid/inbound-mail-parser no tiene documentación, sin embargo, no funcionó para mí. El constructor de mailParse toma request como parámetro, no el cuerpo de la solicitud.

const parsing = new mailParse(config, req);

Hola @ZeroCho ,

Tenemos un paquete aquí , pero desafortunadamente no hay una buena documentación de uso. Para eso, es posible que desee consultar el analizador de entrada de Python .

Con los mejores deseos,

Elmer

Entonces deberías escribir documentación.

¿Cómo es esto todavía indocumentado?

todavía no puedo resolverlo con nodejs express ...

Reapertura ya que todavía no hay un ejemplo de esto en los documentos.

Las solicitudes de extracción para agregar esta función son bienvenidas y se revisarán en función de la prioridad, pero Twilio SendGrid no está creando activamente nuevas funciones para la biblioteca.

Tratando de recibir archivos adjuntos, pero aún así no tuve suerte ...

Tratando de recibir archivos adjuntos, pero aún así no tuve suerte ...

Usar 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));
            });

Estoy intentando eso pero sin suerte ... devuelve un objeto vacío y cuando lo hago .attachments() también obtengo una matriz vacía.

Estoy usando funciones en la nube de firebase, no he tenido ningún éxito con el analizador de correo entrante y espero con ansias alguna documentación que pueda ayudarme a usar la biblioteca ...

Pero usar busboy (y deseleccionar "raw" en la configuración de Sendgrid) está funcionando bastante bien, excepto por un problema que me llevó a intentar usar el analizador de correo ...

Sendgrid enumera las diferentes codificaciones en el campo "conjuntos de caracteres" de esta manera:
Un correo electrónico de Gmail:
{"a": "UTF-8", "html": "UTF-8", "asunto": "UTF-8", "de": "UTF-8", "texto": "UTF-8" }
Un correo electrónico de Outlook:
{"a": "UTF-8", "html": "iso-8859-1", "asunto": "UTF-8", "de": "UTF-8", "texto": "iso- 8859-1 "}

Cuando los correos electrónicos contienen caracteres internacionales (como ÆØÅ), el resultado es que los campos de texto y html contienen signos de interrogación en lugar de los caracteres nórdicos reales.

Si cambio defCharset en busboy a Windows-1252, los valores de texto y html se mostrarán correctamente, pero los otros campos se mostrarán incorrectamente.

¿Será esto un problema también en el analizador de correo, o el analizador de correo maneja diferentes codificaciones en los campos?

Mi código para analizar usando busboy para cualquier persona interesada:
(Si alguien puede decirme cómo resuelvo el problema anterior usando ayudante de camarero, estaría agradecido ...)

exportaciones.sendgridparse = functions.https.onRequest ((req, res) => {
const ruta = require ('ruta');
const os = require ('os');
const fs = require ('fs');
const Busboy = require ('ayudante de camarero');

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;
});

dejar imageToBeUploaded = {};
let imagestobeuploaded = [];
let imageFileName;

busboy.on ('archivo', (nombre de campo, archivo, nombre de archivo, codificación, tipo mime) => {
console.log (nombre de campo, archivo, nombre de archivo, codificación, tipo mime);

file.on ('datos', función (datos) {
console.log ('Archivo [' + nombre de campo + '] obtuvo' + data.length + 'bytes');
});
file.on ('end', function () {
console.log ('Archivo [' + nombre de campo + '] Finalizado');
});

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 = {ruta de archivo, mimetype, imageFileName, imageExtension, url};
imagestobeuploaded.push (imageToBeUploaded);
file.pipe (fs.createWriteStream (ruta de archivo));
});

busboy.on ('finalizar', async () => {
// todos los campos están disponibles (imágenes para cargar y campos) y se pueden guardar en la base de datos
res.send (200);
});
busboy.end (req.rawBody);
});

@hhetland entonces, ¿

@matheustavaresdev - Sí,

Primero se guardan en una carpeta tmp en busboy.on ('archivo'), y luego, usando la información en la variable "imagestobeuploaded", la guardo en un depósito de almacenamiento en firebase en busboy.on ('terminar').

¡¡¡¡¡¡¡¡¡¡¡¡genial gracias!!!!!!!!!!!!

Abril de 2020, todavía no hay documentos oficiales, ¿verdad?

Sé que esto se ha cerrado, pero acabo de detectar este problema y tengo Express con inbound-mail-parser funcionando. Lo principal que tenía que hacer era usar la biblioteca multer para manejar la entrada multipart / form-data y luego usar el método keyValues ​​() de la biblioteca @ sendgrid / inbound-mail-parser como se muestra a continuación

require en multer y Sendgrid:

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

en la declaración de mi enrutador para el método POST, use el método upload.none () ya que solo estaba recibiendo texto (sin archivos adjuntos):

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

Dentro de esa definición POST, luego uso el método keyValues ​​() para obtener las partes relevantes del correo electrónico:

tratar {
const config = {claves: ['a', 'desde', 'asunto', 'texto',]};
análisis constante = new mailParse (config, req.body);
dejar respuesta = parsing.keyValues ​​();
let to = response.to;
dejar de = respuesta. de;
let subject = response.subject;
dejar messageBody = response.text
console.log ('Este es el asunto del correo:', asunto);
}

Espero que sea de alguna utilidad.

Lo que encuentro es que request.body está en form-data y veo un error:
[Nest] 24687 - 05/01/2020, 1:29:51 PM [ExceptionsHandler] Reducción de matriz vacía sin valor inicial
TypeError: reducción de una matriz vacía sin valor inicial
en Array.reduce ()

El código:
keyValues ​​() {
devuelve esto.
.filter (clave => this.payload [clave])
.map (clave => ({[clave]: this.payload [clave]}))
.reduce ((keyValues, keyPayload) => Object.assign (keyValues, keyPayload));
}

devuelve un error ya que this.payload no es un dato estructurado sino un dato de formulario de varias partes.

No pude hacer que esto funcionara con nest-js. Los datos de webhook que recibo en el controlador de NestJS son datos de varios formatos. No estoy seguro de cómo usar Multer en ese caso.

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

Intenté hacer esto:

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(); } }

Sin embargo, el req.body devuelve:
request: [Object: null prototype] {}

El antes imprime datos multiforma.

Estos son los cambios que tuve que hacer para poder usar multer:

app.use (express.json ())
app.use (express.urlencoded ({extendido: verdadero}));
carga constante = multer ();
app.use (upload.none ());

Una vez que hice esto, pude usar multer para analizar los datos del webhook en un
clave estructurada, par de valores.

El domingo, 24 de mayo de 2020 a las 4:51 p. M. Danés Mohd [email protected]
escribió:

Si no tiene servidor (funciones en la nube de Google o Firebase)
esto podría ayudar:
https://stackoverflow.com/questions/47242340/how-to-perform-an-http-file-upload-using-express-on-cloud-functions-for-firebase/48648805#48648805

Utilice Formidable para analizar varias partes en servidores sin servidor:
https://github.com/DanisHack/formidable-serverless

-
Estás recibiendo esto porque comentaste.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/sendgrid/sendgrid-nodejs/issues/482#issuecomment-633312295 ,
o darse de baja
https://github.com/notifications/unsubscribe-auth/AB2ATHHFKBRZZDGGJ2D7SOLRTGQHNANCNFSM4D67CVZQ
.

-

Shweta Bhandare, PhD | Ingeniero de software principal

[email protected]

https://hicleo.com/
hicleo.com | Linkedin https://www.linkedin.com/company/hicleo/ | Gorjeo
https://twitter.com/hi_cleo/ | Instagram
https://www.instagram.com/hicleo.co/ | Facebook
https://www.facebook.com/hicleolabs

-

Este mensaje puede contener información confidencial, patentada o protegidainformación.
Si recibió este mensaje por error,notifique al remitente por correo electrónico de respuesta y elimine este mensaje.

Pasamos mucho tiempo tratando de hacer que esto funcionara en Google Cloud Functions con Busboy y no pudimos hacerlo realidad sin importar qué tutorial o sugerencias seguimos.

Así que dejaré esto aquí para la próxima persona en una situación similar en la que tenga un poco de flexibilidad: use el analizador de entrada de Python . Fue más o menos un trabajo de copiar / pegar del código que proporcionan y tardó menos de una hora en ejecutarlo.

Sé que esto no resuelve el problema aquí, pero espero que pueda ahorrarle a alguien más horas de headbanging.

Me alegro de haber encontrado este boleto ... Me estaba volviendo loco tratando de encontrar documentación sobre esto, y de alguna manera no hay ninguna .

De hecho, estoy desconcertado. Simplemente asumí que habría documentación estándar, especialmente porque si bien es de código abierto, está respaldado por SendGrid (y, en última instancia, Twilio, que tiene una documentación fantástica).

Para algo tan simple como esto, imaginarías que al menos habría un ejemplo.

No obstante, para cualquiera que se encuentre con esto ...

Recomiendo usar MailParser en

Estoy bastante seguro de que esto lo usa bajo el capó, pero al menos MailParser tiene mucha documentación. Solo asegúrese de que en su configuración de análisis entrante tenga POST the raw, full MIME message marcado como se muestra a continuación (_wow, un ejemplo_).

Example

Leyendo los documentos de MailParser, lo hice en minutos:

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);
};

Todos los datos son como le gustaría.

También utilizo el middleware Multer para analizar los datos de formularios / múltiples partes que envía SendGrid POST a mi punto final.

Es tan simple como multer().any() dentro de su flujo de middleware.

Salud

Usé el mensaje MIME completo sin procesar y lo hice funcionar con simpleParser, pero estoy volviendo a la versión procesada y usando el analizador de correo entrante de sengrid porque simpleParser no convierte el MIME a texto y html tan bien.

Sin embargo, definitivamente necesito algo de documentación.

@theweiweiway ¿Le importaría publicar un ejemplo de la diferencia en texto y html entre los dos métodos? No he notado ninguna diferencia y tengo curiosidad.

para texto

Hi 123 Hi 123 Hi 123 www.hello.com

vs

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

^ no sé por qué sucedió eso

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

vs

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

Creo que tiene más que ver con el paquete simpleParser aunque

Aquí está mi repositorio express-sendgrid-inbound-parse usando express / multer. Es una aplicación fácil para comenzar. Recomiendo dejar POST the raw, full MIME message sin marcar ya que puede acceder a más datos de correo electrónico.

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'])
}

probé esto en la función de nube de base de fuego.
No trabajes definitivamente.
¿Alguna otra solución?

¿Fue útil esta página
0 / 5 - 0 calificaciones